WebHU - Programozási kérdések és válaszok

Van egy próbálkozás a Convert.ToInt32-vel, elkerülve a kivételeket

Érdeklődni szeretnék, hogy van-e "biztonságos" módszer egy objektum int-re való konvertálására, elkerülve a kivételeket.

olyasmit keresek, mint public static bool TryToInt32(object value, out int result);

Tudom, hogy valami ilyesmit tudnék készíteni:

public static bool TryToInt32(object value, out int result)
{
    try
    {
        result = Convert.ToInt32(value);
        return true;
    }
    catch
    {
        result = 0;
        return false;
    }
}

De inkább kerülöm a kivételeket, mert lassítják a folyamatot.

Szerintem ez elegánsabb, de így is "olcsó":

public static bool TryToInt32(object value, out int result)
{
    if (value == null)
    {
        result = 0;
        return false;
    }

    return int.TryParse(value.ToString(), out result);
}

Van valakinek jobb ötlete?

FRISSÍTÉS:

Ez kicsit úgy hangzik, mint a szőrszálak felhasítása, de egy objektum karakterláncsá alakítása arra kényszeríti az implementálót, hogy tiszta ToString() függvényt hozzon létre. Például:

public class Percentage
{
    public int Value { get; set; }

    public override string ToString()
    {
        return string.Format("{0}%", Value);
    }
}

Percentage p = new Percentage();
p.Value = 50;

int v;
if (int.TryParse(p.ToString(), out v))
{

}

Ez rosszul sül el, itt két dolgot tehetek, vagy a következőképpen valósíthatom meg a IConvertable-et:

public static bool ToInt32(object value, out int result)
{
    if (value == null)
    {
        result = 0;
        return false;
    }

    if (value is IConvertible)
    {
        result = ((IConvertible)value).ToInt32(Thread.CurrentThread.CurrentCulture);
        return true;
    }

    return int.TryParse(value.ToString(), out result);
}

De a IConvertible ToInt32 metódusát nem lehet törölni. Tehát ha nem lehetséges az érték konvertálása, nem kerülhető el a kivétel.

Vagy kettő: Van mód annak ellenőrzésére, hogy az objektum tartalmaz-e implicit operátort?

Ez nagyon szegényes:

if (value.GetType().GetMethods().FirstOrDefault(method => method.Name == "op_Implicit" && method.ReturnType == typeof(int)) != null)
{
    result = (int)value;
    return true;
}
14.08.2013

  • Miért csomagolja be a TryParse-t? 14.08.2013
  • A TryParse-nak van egy paramétere. 14.08.2013
  • Csak akkor szeretnék kivételt alkalmazni, ha nem számítok rá. Itt a paraméter bármi lehet. Tehát ez a POV, amiből dolgozom. 14.08.2013
  • Ügyeljen arra, hogy a Convert.ToInt32 mást csinál. Megpróbálja átküldeni az objektumot a IConvertible-ba, majd meghívja a ToInt32 metódust. Van egy finom különbség: bármely osztály megvalósíthatja a IConvertible-et, de lehet egy ToString(), amely nem ad vissza karakteres számot. 14.08.2013
  • A kódodhoz hozzáadnék egy ellenőrzést, ha az érték már int. if (value is int) return (int)value; 14.08.2013
  • @xanatos, szerintem az IConvertable felület szép, de az interfész nem teszi lehetővé egy érték törlését/konvertálását. Az implementátornak továbbra is kivételt kell adnia, ha egy érték nem konvertálható. if (az érték IConvertible) { eredmény = ((IKonvertálható)érték).ToInt32(Thread.CurrentThread.CurrentCulture); return true; } 14.08.2013
  • Hú, a meglévő válaszok egyike sem válaszol megfelelően a kérdésre. Túl álmos vagyok ahhoz, hogy választ írjak, de alapvetően ha primitív integráltípusokkal dolgozik, használja a TypeCode-t annak meghatározására, hogy a bemenet előjel nélküli-e ((int)typeCode - 5 & 9) == 1 (feltételezve, hogy nem érdekel char és bool), vagy ha ((int)typeCode - 5 & 9) == 0 jelű, és ennek megfelelően használja a ToUInt64 vagy ToInt64 jelet, akkor ellenőrizze a határokat és a profitot. Minden IConvertible típusú eszköz GetTypeCode(). Most persze, ha egyéni típusoknál is meg szeretné tudni, adjon hozzá saját felületet, és ellenőrizze a konvertálásban. 08.06.2017
  • Az Object.ToString helyett használja a String.Format-ot numerikus formátum-specifikációval, azaz D-vel, ehhez nem lesz szükség az objektumoknak az alapértelmezett ToString felülírására. 14.03.2020

Válaszok:


1
int variable = 0;
int.TryParse(stringValue, out variable);

Ha nem lehet elemezni, a változó 0 lesz. Lásd: http://msdn.microsoft.com/en-us/library/f02979c7.aspx

14.08.2013
  • Ez sikertelen lesz, ha átad egy objektumot a TryParse-nak. 14.08.2013
  • Megbízhatóbb: int variable=int.TryParse(stringValue, out variable) ? variable : 0 21.08.2014
  • @KaiHartmann: A TryParse karakterláncot vár, nem objektumot. De még akkor is, ha egy objektumot használ, és a int.TryParse(myObject.Tostring() , out result)-t hívja, az továbbra is működne minden (nem nulla) értéknél. A null értékekre kapott Nullreference kivételnek semmi köze a TryParse-hoz, inkább a .ToString() meghívásához. 10.01.2017
  • Ha stringValue egyenlő 0-val, akkor a rendszer sikeresen értelmezi, és a variable továbbra is 0 lesz. Ellenőrizze a TryParse visszatérési értékét. 03.09.2018
  • A @Rango válasza jelenleg a legjobb válasz a használati esetemben. 18.01.2019

  • 2

    A kommentekből kiindulva. A válasz nem. Nem teheti meg azt, amit Convert.ToInt32(object) tesz kivételek nélkül. Csinálhatsz valami hasonlót (és már megtetted). Az egyetlen dolog, amit optimalizálnék, az a value esete, amely már int.

    if (value is int) 
        return (int)value;
    

    Nem teheti meg, hogy Convert.ToInt32(object), mert a Convert.ToInt32(object) nem egyszerűen teszteli, hogy a value short, int, long, ushort, ...-e, majd átküldi őket. Ellenőrzi, hogy a value értéke IConvertible. Ha igen, akkor a IConvertible.ToInt32-t használja. Sajnos a IConvertible felület elég gyenge: nincsenek nem dobó módszerek (IConvertible.Try*)

    Bár hülyeség (de talán nem túl sok), valaki készíthet például egy UnixDateTime struktúrát: (A UnixTime a másodpercek száma 1970-01-01 éjféltől), ahol a IConvertible.ToInt32 ezt a másodpercszámot adja vissza, míg a ToString() egy formázottat. dátum. Az összes int.TryParse(value.ToString(), out parsed) megfulladna, míg a Convert.ToInt32 hibátlanul működne.

    14.08.2013
  • Ha egy IConvertible-t használunk paraméterként a metódusban az objektum helyett, az nem oldaná meg a problémát? Példaként lásd a válaszomat. 14.08.2013
  • @KaiHartmann Nem, ha már van object. object obj = 5.5. A MyConvert.ToInt32() a object túlterhelést választaná a IConvertible túlterhelés helyett. 14.08.2013

  • 3

    Itt nem kell újra feltalálni a kereket. használja a int.TryParse segítségével elérheti célját. Bool értéket ad vissza, jelezve, hogy az érték értelmezve van-e vagy sem. és ha elemezzük az eredményt a kimeneti változóba mentjük.

    int result;
    object a = 5;
    if(int.TryParse(a.ToString(),out result))
    {
       Console.WriteLine("value is parsed");  //will print 5
    }    
    
    object b = a5;
    if(int.TryParse(b.ToString(),out result))
    {
        Console.WriteLine("value is parsed");  
    }
    else
    {
        Console.WriteLine("input is not a valid integer");  //will print this   
    }
    
    14.08.2013
  • Ez sikertelen lesz, ha átad egy objektumot a TryParse-nak. 14.08.2013
  • @KaiHartmann igen, ehhez sztring kell. És ha van objektuma, először meg kell hívnia a ToString metódust. frissítette a válaszomat. 14.08.2013

  • 4

    Ez a típusátalakítót használó verzió csak végső megoldásként konvertálna karakterláncra, de nem jelent kivételt:

    public static bool TryToInt32(object value, out int result)
    {
        if (value == null)
        {
            result = 0;
            return false;
        }
        var typeConverter =  System.ComponentModel.TypeDescriptor.GetConverter(value);
        if (typeConverter != null && typeConverter.CanConvertTo(typeof(int)))
        {
            var convertTo = typeConverter.ConvertTo(value, typeof(int));
            if (convertTo != null)
            {
                result = (int)convertTo;
                return true;
            }
        }
        return int.TryParse(value.ToString(), out result);
    }
    
    31.05.2016
  • +1 érdekes és más válasz. De ez valóban egy nagyon körkörös módja a régi IConvertible metódusok használatának. A probléma része itt is a CanConvertTo metódus. Egyszerűen nem azt csinálja, amit akarunk – azt akarjuk, hogy a válasz a tényleges értéktől függjön: azt akarjuk, hogy a long egy int-be önthető legyen ha az abban tárolt érték belefér egy intbe. Ez a metódus túlcsordulási kivételt ad, ha megpróbálja átküldeni a long.MaxValue elemet egy int-re, mert a CanConvertTo nem azt csinálja, amit Ön gondol, valójában igazat ad vissza minden primitív típusra! 08.06.2017

  • 5

    Keveréket használnék abból, amit már csinálsz;

    • Ellenőrizze, hogy az objektum nulla-e - adjon vissza false értéket és 0 értéket;
    • Próbálja meg közvetlenül konvertálni – ha sikeres, adja vissza a true értéket és a konvertált értéket
    • Kísérlet az érték elemzésére.ToString() - ha sikeres, adja vissza true és az elemzett értéket
    • Minden más eset - Hamis értéket ad vissza és 0 értéket, mivel az objektum nem konvertálható/parbilis

    A kapott kód:

    public static bool TryToInt32(object value, out int result)
    {
        result = 0;
        if (value == null)
        {
            return false;
        }
    
        //Try to convert directly
        try
        {
            result = Convert.ToInt32(value);
            return true;
        }
        catch
        {
            //Could not convert, moving on
        }
    
        //Try to parse string-representation
        if (Int32.TryParse(value.ToString(), out result))
        {
            return true;
        }
    
        //If parsing also failed, object cannot be converted or paresed
        return false;
    }
    
    14.08.2013
  • Miért adjam át referenciaként? 14.08.2013
  • @JeroenvanLangen, Mert az eredménynek meg kell tartania az eredeti értékét, ha nem konvertálják - frissítettem a választ. 14.08.2013
  • @JeroenvanLangen, úgy tűnik, tévedtem. Újra frissítem a választ. De ennek ellenére úgy tűnik, ez a hármas ellenőrzés az, amit akarsz. 14.08.2013

  • 6

    Egy nullázható int. így megtudhatja, hogy elemezte-e a 0-t.

    int? value = int.TryParse(stringValue, out int outValue) 
        ? outValue
        : default(int?);
    
    02.11.2018
  • A próbálkozási módszereknek vissza kell adnia a bool-t. 14.03.2020
  • @user3285954 ez a TryParse metódus megteszi. Háromtagú operátort használok. A TryParse-ból visszaadott logikai érték határozza meg, hogy outValue vagy default(int?) 18.03.2020

  • 7

    Én írtam ezt a káoszt, elszomorít a nézés.

    using System;
    using System.Globalization;
    
    internal static class ObjectExt
    {
        internal static bool TryConvertToDouble(object value, out double result)
        {
            if (value == null || value is bool)
            {
                result = 0;
                return false;
            }
    
            if (value is double)
            {
                result = (double)value;
                return true;
            }
    
            var text = value as string;
            if (text != null)
            {
                return double.TryParse(text, NumberStyles.Float, CultureInfo.InvariantCulture, out result);
            }
    
            var convertible = value as IConvertible;
            if (convertible == null)
            {
                result = 0;
                return false;
            }
    
            try
            {
                result = convertible.ToDouble(CultureInfo.InvariantCulture);
                return true;
            }
            catch (Exception)
            {
                result = 0;
                return false;
            }
        }
    }
    

    Szerkesztés Figyelje meg, hogy duplán válaszoltam, amikor a kérdés int volt, de megtartottam. Talán hasznos valakinek.

    16.09.2016
    Új anyagok

    A rádiógomb ellenőrzött eseményének használata a jQueryben
    Ebben a cikkben látni fogjuk, hogyan kell dolgozni a jquery választógombbal ellenőrzött eseményeivel. A választógombok HTML gombok, amelyek segítenek kiválasztani egyetlen értéket egy csoportból...

    Körkörös függőségek megoldása terraformban adatforrásokkal – lépésről lépésre
    Mi az a körkörös függőségek Dolgozzunk egy egyszerű eseten, amikor az SQS-sor és az S3-vödör közötti körkörös függőség problémája van egy egymástól függő címkeérték miatt. provider..

    Miért érdemes elkezdeni a kódolást 2023-ban?
    01100011 01101111 01100100 01100101 — beep boop beep boop Világunk folyamatosan fejlődik a technológia körül, és naponta fejlesztenek új technológiákat a valós problémák megoldására. Amint..

    🎙 Random Noise #2  – Örökbefogadás és hit
    az analitika íratlan világának gondozása Szeretné, hogy ezek a frissítések a postaládájába kerüljenek? Iratkozzon fel itt . "Ha önvezető autókat gyártanak, akkor mi miért ne..

    A legrosszabb politika és prediktív modellek májátültetésre jelöltek számára az Egyesült Államokban
    A máj (vagy óangolul lifer) az emberi test legnehezebb belső szervére utal, amely csendesen működik a nap 24 órájában. Mit csinál a máj? 500 feladatot hajt végre a szervezet egészségének..

    5 webhely, amely 2022-ben fejleszti front-end fejlesztői készségeit
    Frontendmentor.io A tényleges projektek létrehozásával a Frontendmentor.io segítséget nyújt a front-end kódolási képességeinek fejlesztésében. A kódolást azután kezdheti meg, hogy..

    Mikor kell használni a Type-t az interfészhez képest a TypeScriptben?
    A TypeScript a JavaScript gépelt szuperkészlete, amely statikus gépelést ad a nyelvhez. Ez megkönnyíti a robusztus és karbantartható kód írását azáltal, hogy a hibákat a fordítási időben..