考虑以下代码片段
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”] as TestEnum?”时我得到了一个 NullReferenceException。在调试时。
我想知道这是否表明建议的代码存在潜在问题,将数据库值映射到枚举的首选方法是什么,一般来说您对这种代码有何看法。
最佳答案
建议的代码是错误的 - 它不会抛出异常,但总是计算为 TestEnum.Value1
。
为什么?读取器将值作为 object
返回。 as T?
运算符仅如果对象表示装箱 T
值,则运算符将评估为非空值。当对象像您的情况一样包含 string
时,或者即使是装箱的 int
(枚举的基础类型),运算符 仍然是 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"]);
关于c# - 为什么在调试时而不是在运行时检查时会出现异常/从数据库映射枚举的最佳实践是什么,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44956682/