Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Suppress "Use of unassigned local variable" error?

Tags:

c#

I have a method like so:

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);
}

...now, the variables a, b, c, and d will never be "unassigned" by the point where they would be referenced, but the compiler doesn't see it that way. Is there a way I can force the compiler to just "build it anyway"? It seems silly to initialize these values ahead of time.

like image 656
Jeremy Holovacs Avatar asked Aug 10 '17 13:08

Jeremy Holovacs


3 Answers

Just refactor the code to avoid the pointless local variable that's confusing things, taking advantage of the fact that within the if body, the compiler does know that everything is definitely assigned:

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;
}

Or using a conditional operator (and using shifting for simplicity):

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;
}
like image 108
Jon Skeet Avatar answered Oct 23 '22 02:10

Jon Skeet


No, there is no way to ignore that compile time error, or any compile time error. You will need to ensure that the compiler is capable of proving that no uninitialized local variable is ever read, you can't just tell it to "trust you".

Fortunately, restructuring the code such that the compiler can prove that no uninitialized variable is ever read isn't that hard:

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;
}
like image 3
Servy Avatar answered Oct 23 '22 01:10

Servy


Try something like this instead:

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;
}

The compiler isn't smart enough to realise when success will be true.

like image 1
Derek Avatar answered Oct 23 '22 01:10

Derek