2017-07-06 25 views
1

映射枚舉考慮下面的代碼片段爲何在調試時不能在運行時檢查時,我得到一個異常/什麼是從DB

public class Class1 
{ 
    public enum TestEnum 
    { 
     Value1 = 1, 
     Value2 = 2 
    } 
    public void TestCall() 
    { 
     /*some standard DB code returning an SqlDataReader...*/ 
     SqlDataReader rdr = com.ExecuteReader(); 
     Item item = new Item(); 

     /*original code*/ 
     /*Database "Type" is a varchar() field containing an integer, please dont ask why :)*/ 
     if (rdr["Type"].GetType() == typeof(DBNull)) 
     { 
      item.Type = TestEnum.Value1; 
     } 
     else if ((string)rdr["Type"] == "1") 
     { 
      item.Type = TestEnum.Value2; 
     } 
     else if ((string)rdr["Type"] == "2") 
     { 
      item.Type = TestEnum.Value1; 
     } 
     else 
     { 
      item.Type = TestEnum.Value1; 
     } 

     /*suggested code*/ 
     item.Type = rdr["Type"] as TestEnum? ?? TestEnum.Value1; //<- default/null value to use 
    } 
} 
public class Item 
{ 
    public Class1.TestEnum Type; 
} 

在代碼審查,我的一個同事的最佳實踐指出我可以用一行代碼(「原代碼」)替換級聯IF(「原代碼」)

雖然建議的代碼運行得很好,但在檢查「rdr [」Type「]時,我得到一個NullReferenceException作爲TestEnum?「在調試時。

我想知道這是否是建議代碼的底層問題的標誌,將數據庫值映射到枚舉的最佳方式是什麼,以及您對這類代碼的總體思路是什麼。

+1

正常的方法是閱讀數據庫值作爲int並將其轉換爲枚舉,如果它們具有相同的基礎值。 –

+0

c#代碼的字段是一個整數(更具體地說是一個枚舉),但數據庫類型是一個varchar();這是奇怪的,不推薦,但超出我的控制(數據庫來自客戶端,不能修改) –

+0

然後,我建議的方法可能是你應該做的。如果你只有幾個值(比如那些2),那麼你的方法無論如何是好的 –

回答

2

建議的代碼是錯的 - 它不會拋出異常,但總是會評估爲TestEnum.Value1

爲什麼?讀者返回值爲objectas T?運營商將評估爲非空值只有如果對象代表盒裝T值。當對象包含string與您的情況相同,或者即使是盒裝的int(您的枚舉的基礎類型),仍然運算符as TestEnum?將評估爲null,因此該表達式將遇到?? TestEnum.Value1條件。

不久,不要依賴這樣的技巧。 (如果需要的話,可以從其他地方重複使用)如果您想改善的代碼,創建一個方法:

static TestEnum ToTestEnum(object dbValue) 
{ 
    TestEnum value; 
    return Enum.TryParse(dbValue as string, out value) ? value : TestEnum.Value1; 
} 

,然後改變其原來的代碼一樣

item.Type = ToTestEnum(rdr["Type"]); 
相關問題