将 null 转换为某些内容

本文关键字:null 转换 | 更新日期: 2023-09-27 18:34:32

我今天和一位同事进行了有趣的讨论。我们正在讨论 C# 中的两段代码。

代码片段 1:

if(!reader.IsDBNull(2))
{
  long? variable1 = reader.GetInt64(2)
}

代码片段 2:

long variable1 = reader.IsDBNull(2) ? (long?) null : reader.GetInt64(2)

问题是:将 null 转换为可为空的长整型是否是一种好的做法?或者,您是否宁愿使用传统的 if 语句来避免将null转换为可为空的长整型。

将 null 转换为某些内容

表达式

(type?)nulldefault(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 的类型,则可以自由使用您最喜欢的版本。但请注意,应尽量避免使用可为 null 类型的算术。如果要从条件表达式返回可为 null 的值,如果其中一个结果可以为 null,则两个可能的结果都必须可为 null。在这种情况下,任何其他方式都可能导致异常。

而不是

(long?) null

default(long?) 

我会重构上面的代码,例如

long? variable1 = reader.IsDBNull(2) ? default(long?) : reader.GetInt64(2)

我不想铸造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);
片段

2 在我的情况下是值得的,就像在null的情况下你会得到0,这是一个完全有效的值long

在 C# 7.1 中,您可以使用更简洁default文字:

var variable1 = reader.IsDBNull(2) ? default : reader.GetInt64(2);