我今天和一位同事进行了这次有趣的讨论。我们在C#中讨论了两段代码。
代码段1:
if(!reader.IsDBNull(2))
{
long? variable1 = reader.GetInt64(2)
}
代码段2:
long variable1 = reader.IsDBNull(2) ? (long?) null : reader.GetInt64(2)
问题是:将null转换为可空的long是一个好习惯吗?或者您是否愿意使用传统的if语句来避免将null
强制转换为可为空的长。
答案 0 :(得分:15)
表达式(type?)null
,default(type?)
和new Nullable<type>()
最终被编译为相同的操作码:
long? x = (long?)null;
long? y = default(long?);
long? z = new Nullable<long>();
变成了:
IL_0001: ldloca.s x
IL_0003: initobj valuetype [mscorlib]System.Nullable`1<int64>
IL_0009: ldloca.s y
IL_000b: initobj valuetype [mscorlib]System.Nullable`1<int64>
IL_0011: ldloca.s z
IL_0013: initobj valuetype [mscorlib]System.Nullable`1<int64>
换句话说,如果您正在使用可空类型,则可以自由使用您最喜欢的版本。但请注意,您应该尽量避免使用可空类型的算术。如果要从条件表达式返回可为空的值,则如果其中一个可以为null,则两个可能的结果必须是可为空的。在这种情况下,任何其他方式都可能导致异常。
答案 1 :(得分:3)
而不是
(long?) null
使用
default(long?)
我会像
那样重构上面的代码long? variable1 = reader.IsDBNull(2) ? default(long?) : reader.GetInt64(2)
答案 2 :(得分:1)
我不想施放null
值(对我来说看起来很奇怪):
long? variable1 = reader.IsDBNull(2) ? null : (long?)reader.GetInt64(2);
另一种选择:
long? variable1 = reader.IsDBNull(2) ? default : reader.GetInt64(2); // requires C# 7.1
long? variable1 = reader.IsDBNull(2) ? default(long?) : reader.GetInt64(2);
long? variable1 = reader.IsDBNull(2) ? (long?)null : reader.GetInt64(2);
long? variable1 = reader.IsDBNull(2) ? new Nullable<long>() : reader.GetInt64(2);
long? variable1 = reader.IsDBNull(2) ? new long?() : reader.GetInt64(2);
long? variable1 = reader.IsDBNull(2) ? null : new long?(reader.GetInt64(2));
这只是品味的问题。我认为第一个选项比其他选项更具可读性。
更新:考虑编写一些扩展方法,使代码更清晰:
public static class DataReaderExtensions
{
public static long? GetNullableInt64(this IDataReader reader, int index)
{
if (reader.IsDBNull(index))
return null;
return reader.GetInt64(index);
}
}
在这种情况下,你不使用三元运算符(没有强制转换为可空),从阅读器读取值看起来更漂亮:
long? variable1 = reader.GetNullableInt64(2);
答案 3 :(得分:0)
小部件2在我的情况下是值得的,例如null
你将得到0
,这是long
的完全有效值
答案 4 :(得分:0)
在C#7.1中,您可以使用more concise default
literal:
var variable1 = reader.IsDBNull(2) ? default : reader.GetInt64(2);