5

我今天和一位同事进行了一次有趣的讨论。我们在 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为可空长。

4

5 回答 5

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>

换句话说,如果您使用可空类型,您可以自由使用您最喜欢的任何版本。但是请注意,您应该尽量避免使用可为空类型的算术。如果要从条件表达式中返回一个可为空的值,则如果其中一个可能为空,则这两个可能的结果都必须可为空。在这种情况下,任何其他方式都可能导致异常。

于 2012-05-17T10:41:32.583 回答
3

Instead of

(long?) null

use

default(long?) 

I would refactor above code like

long? variable1 = reader.IsDBNull(2) ? default(long?) : reader.GetInt64(2)
于 2012-05-17T10:30:54.123 回答
1

I prefer not to cast null value (it looks odd to me):

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

Another options:

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));

It's just the matter of taste. I think first option is more readable, than others.

UPDATE: Consider also writing some extension methods to make your code more clear:

public static class DataReaderExtensions
{
    public static long? GetNullableInt64(this IDataReader reader, int index)
    {
        if (reader.IsDBNull(index))
            return null;

        return reader.GetInt64(index);
    }
}

In this case you don't use ternary operator (no casting to nullable), and reading values from reader looks more pretty:

long? variable1 = reader.GetNullableInt64(2);
于 2012-05-17T10:29:18.450 回答
0

Snippet 2 is worth in my case, as in case of null you're gonna get 0, which is a completely valid value for long

于 2012-05-17T10:30:27.680 回答
0

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

var variable1 = reader.IsDBNull(2) ? default : reader.GetInt64(2);
于 2018-09-20T13:00:06.830 回答