2017-08-10 16 views
5

Mam metodę tak:Usunąć błąd "Użyj nieprzypisanej zmiennej lokalnej"?

public static long? FromIpv4ToLong(this string ipAddress) 
{ 
    var octets = ipAddress.Split(IpSplitChar); 
    if (octets.Length != 4) return null; 

    var success = long.TryParse(octets[0], out long a) 
        && long.TryParse(octets[1], out long b) 
        && long.TryParse(octets[2], out long c) 
        && long.TryParse(octets[3], out long d); 

    if (!success) return null; 

    return ((16777216L * a) + (65536L * b) + (256L * c) + d); 
} 

... teraz, zmienne a, b, c, a d nigdy nie będzie „nieprzypisane” przez miejsca, w którym będą się odwoływać, ale kompilator nie robi nie widzisz tego w ten sposób. Czy istnieje sposób, w jaki mogę zmusić kompilator do "zbudowania go w każdym razie"? Wydaje się głupim zainicjowanie tych wartości z wyprzedzeniem.

+4

Należy rozważyć użycie 'IPAddress.TryParse' będzie to akceptują nieprawidłowe adresy IP4 . – Lee

+0

Pracuję w celu wymiany reklam online; przetwarzamy adresy IP 60-100K na sekundę, z SLA o długości dwóch cyfr milisekund. 'IPAddress.TryParse' dodaje zauważalne opóźnienie i dlatego jest verboten. Możemy użyć tylko najprostszych, najszybszych i najbardziej wydajnych algorytmów do tego typu rzeczy. –

Odpowiedz

12

Wystarczy byłaby kod, aby uniknąć niepotrzebnego zmiennej lokalnej, która jest mylące rzeczy, korzystając z faktu, że w organizmie if, kompilator dokłada wiedzieć, że wszystko jest na pewno przypisane:

public static long? FromIpv4ToLong(this string ipAddress) 
{ 
    var octets = ipAddress.Split(IpSplitChar); 
    if (octets.Length != 4) return null; 

    if (long.TryParse(octets[0], out long a) 
     && long.TryParse(octets[1], out long b) 
     && long.TryParse(octets[2], out long c) 
     && long.TryParse(octets[3], out long d) 
    { 
     return (16777216L * a) + (65536L * b) + (256L * c) + d; 
    } 

    return null; 
} 

lub przy użyciu operator warunkowy (z użyciem przesunięcia dla uproszczenia):

public static long? FromIpv4ToLong(this string ipAddress) 
{ 
    var octets = ipAddress.Split(IpSplitChar); 
    return octets.Length == 4 
     && long.TryParse(octets[0], out long a) 
     && long.TryParse(octets[1], out long b) 
     && long.TryParse(octets[2], out long c) 
     && long.TryParse(octets[3], out long d) 
     ? (a << 24) | (b << 16) + (c << 8) | d 
     : null; 
} 
+0

Myślę, że to interesujące, że kompilator może to zrozumieć, ale nie drugi. Dzięki za wgląd. –

+2

@JeremyHolovacs: Aby Twój oryginalny kod działał, ich kompilator musiałby dołączyć istotność do wartości zmiennej 'success'. Istnieje duża różnica między tym a zrozumieniem przepływu kodu w odniesieniu do "jeśli X i Y zostały wykonane, wtedy wszelkie zmienne przypisane w X i Y powinny być traktowane jako zdecydowanie przypisane". –

+0

Czasami rozpieszcza mnie to, co kompilator wie o moich zamiarach, do tego stopnia, że ​​zaskakuje mnie, gdy nie działa. –

1

Spróbuj coś takiego zamiast:

public static long? FromIpv4ToLong(this string ipAddress) 
{ 
    var octets = ipAddress.Split(IpSplitChar); 
    if (octets.Length != 4) return null; 

    if (long.TryParse(octets[0], out long a) 
       && long.TryParse(octets[1], out long b) 
       && long.TryParse(octets[2], out long c) 
       && long.TryParse(octets[3], out long d)){ 
     return ((16777216L * a) + (65536L * b) + (256L * c) + d); 
    } 

    return null; 
} 

Kompilator nie jest wystarczająco inteligentny, aby stwierdzić, kiedy sukces będzie prawdziwy.

3

Nie, nie można zignorować tego błędu czasu kompilacji ani błędu czasu kompilacji. Musisz będzie będzie musiał zapewnić, że kompilator jest w stanie udowodnić, że nie niezainicjowana zmienna lokalna jest kiedykolwiek czytać, nie można po prostu powiedzieć, aby "zaufać ci".

szczęście restrukturyzacji kod taki, że kompilator może udowodnić, że nie jest zmienna niezainicjowany kiedykolwiek czytać nie jest trudne:

public static long? FromIpv4ToLong(this string ipAddress) 
{ 
    var octets = ipAddress.Split(' '); 
    if (octets.Length != 4) return null; 

    if (long.TryParse(octets[0], out long a) 
        && long.TryParse(octets[1], out long b) 
        && long.TryParse(octets[2], out long c) 
        && long.TryParse(octets[3], out long d)) 
    { 
     return ((16777216L * a) + (65536L * b) + (256L * c) + d); 
    } 

    return null; 
} 
Powiązane problemy