2017-08-10 58 views
5

我有这样一个方法,以便:禁止“使用未分配的本地变量”错误?

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

...现在,变量abcd绝不会由他们将要参考的点“未分配”,但没有按编译我不会这样看的。有没有一种方法可以强制编译器“无论如何”构建它?提前初始化这些值似乎很愚蠢。

+4

您应该考虑使用'IPAddress.TryParse',这将接受无效IP4地址。 – Lee

+0

我为在线广告交换工作;我们每秒处理60-100K个IP地址,具有两位数的毫秒延时SLA。 'IPAddress.TryParse'增加了明显的等待时间,因此是不合理的。我们只能使用最简单,最快,最有效的算法来处理这类事情。 –

回答

12

只是重构代码,避免无谓的局部变量这混乱的东西,走的事实if体内,编译器确实知道这一切是绝对分配优势:

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

或者使用条件操作符(以及使用移为简单起见):

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

我认为有趣的是,编译器可以弄清楚,但不是另一个。感谢您的洞察力。 –

+2

@JeremyHolovacs:为了让您的原始代码正常工作,他们的编译器将不得不重视“成功”变量的值。 “如果X和Y都被执行,那么在X和Y中分配的任何变量都应该被视为明确赋值”,这与代码流的理解有很大的区别。 –

+0

有时候我会被编译器对我的意图的理解所迷惑,当它没有时,我会惊讶于它。 –

1

尝试是这样的,而不是:

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

编译器不够智能,无法实现何时成功。

3

不,没有办法忽略编译时错误或任何编译时错误。你需要需要确保编译器能够证明没有未初始化的本地变量被读取,你不能只是告诉它“信任你”。

幸运的是,重组代码,这样编译器可以证明没有初始化的变量读过并不难:

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