2017-08-10 43 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; 
} 
相關問題