Bezpieczniej z TryParse()

Zwyczajny, często widziany kod który parsuje stringa na inta.

int Foo(string value)
{
    var pageId = string.IsNullOrEmpty(value)
        ? 0
        : int.Parse(value);

    return pageId;
}

W zależności od tego czy jesteśmy pewni, że przekazany string ładnie się sparsuje, powyższa funkcja może wystarczyć lub nie.

Fakt, że dostajemy string już mówi, że coś może pójść nie tak. Gdybyśmy mogli przekazać int to byśmy tak zrobili, a nie przechodzili przez inne typy danych. Najpewniej jest to jednak z niepewnego źródła i coś jednak (rzadko, bo rzadko) się wykrzaczy. A do tego w najgorszym momencie i będzie trudne do zlokalizowania 🙂

Bardziej odporny na złośliwości jest kod:

int BetterFoo(string value)
{
    int pageId;

    if (int.TryParse(value, out pageId))
    {
        return pageId;
    }

    return 0;
}

Szczególnie ciekawie (chociaż może myląco) wygląda przypadek, gdy nie sprawdzamy czy TryParse() się udało. Fallbackiem będzie tutaj zero:

int AnotherBetterFoo(string value)
{
    int pageId;

    int.TryParse(value, out pageId);

    return pageId;
}

7 Comments on “Bezpieczniej z TryParse()

  1. Pingback: dotnetomaniak.pl

  2. Cześć, a co jakby to tak zrobić:

    int YetAnotherBetterFoo(string value)
    {
    int pageId = 0;
    int.TryParse(value, out pageId);
    return pageId;
    }

    Seb.

  3. Jedyna zmiana jaką widzę to inicjalizowanie pageId zerem. Jest to zbędne ponieważ metoda TryParse() przyjmuje pageId z parametrem „out”. To znaczy, że cokolwiek zostanie przypisane wcześniej zostanie nadpisane wewnątrz TryParse().
    Resharper ostrzeże nawet że to inicjalizowanie zerem to „Value assigned is not used in any execution path”.

    • Faktycznie, człowiek uczy się cały czas. Dzięki!

  4. [csharp]
    public int? ParseInt(string val)
    {
    int outValue;
    return int.TryParse(val, out outValue) ? (int?)outValue : null;
    }
    [/csharp]

    Dzięki temu można robić łancuszki z operatorem ?? np. int number = ParseInt(x.Num1) ?? ParseInt(x.Num2) ?? 10;

  5. Fajne zastosowanie tej metody z ??. Bardzo ładnie się „łańcuszkuje”.
    Przestrzegałbym jednak przed tworzeniem takiej metody jako globalnego Helpera, który raz się przydał i liczymy, że inni będą go reużywać. Widzę dobre zastosowanie jako prywatna metoda w klasie która ma wiele takich operacji.

  6. To samo można powiedzieć o dowolnej klasie typu Helper. Należy po prostu skonsultować rozpropagować uniwersalne rozwiązania np. poprzez wiki, team space, dokumentacje, spotkań projektowych, code review itp…