检查 null 时,泛型函数是否将值类型隐式转换为对象? [英] Does a generic function implicitly cast value types to objects when checking for null?

查看:44
本文介绍了检查 null 时,泛型函数是否将值类型隐式转换为对象?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

例如下面的代码展示了我的思路:

For example the following code demonstrates my line of thought:

class Program
{
    static void Main(string[] args)
    {
        int i = 0;
        IsNull(i);  // Works fine

        string s = null;
        IsNull(s);  // Blows up
    }

    static void IsNull<T>(T obj)
    {
        if (obj == null)
            throw new NullReferenceException();
    }

}

还有以下代码:

int i = 0;
bool b = i == null;  // Always false

是否正在进行隐式对象转换?使得:

Is there an implicit object cast going on? such that:

int i = 0;
bool b = (object)i == null;

推荐答案

是的,obj 被编译器装箱了.这是为您的 IsNull 函数生成的 IL:

Yes, obj gets boxed by the compiler. This is the IL generated for your IsNull function:

.maxstack 8

IL_0000: ldarg.0
IL_0001: box !!T
IL_0006: brtrue.s IL_000e

IL_0008: newobj instance void [mscorlib]System.NullReferenceException::.ctor()
IL_000d: throw

IL_000e: ret

box 指令是转换发生的地方.

The box instruction is where the casting happens.

编译器不知道关于 T 的任何特定内容,因此它必须假定它必须是 object - .NET 中所有内容的基本类型;这就是为什么它装箱 obj 以确保可以执行空检查.如果您使用 类型约束,您可以向编译器提供更多信息T.

The compiler doesn't know anything specific about T so it must assume that it must be an object - the base type of everything in .NET; this is why it boxes obj to make sure that the null check can be performed. If you use a type constraint you can give more information to the compiler about T.

例如,如果您使用 where T : struct 您的 IsNull 函数将不再编译,因为编译器知道 T 是一个值type 和 null 不是值类型的值.

For example, if you use where T : struct your IsNull function won't compile anymore because the compiler knows T is a value type and null is not a value for value types.

装箱一个值类型实例总是返回一个有效的(非空)对象实例*,所以 IsNull 函数永远不会抛出一个值类型.如果您考虑一下,这实际上是正确的行为:数值 0 不是 null - 值类型值不可能是 null.

Boxing a value type instance always returns a valid (non-null) object instance*, so the IsNull function would never throw for a value type. This is actually correct behavior if you think about it: the numeric value 0 is not null - a value type value cannot possibly be null.

在上面的代码中 brtrue.s 非常像 if(objref!=0) - 它不检查对象的值(值类型装箱前的值),因为在检查时,它不是位于堆栈顶部的值:它是位于顶部的装箱对象实例.由于该值(它实际上是一个指针)是非空的,因此对 null 的检查永远不会返回为真.

In the code above brtrue.s is very much like if(objref!=0) - it doesn't check the value of the object (the value type value before boxing) because at the time of the check, it's not a value that's on top of the stack: it's the boxed object instance that's on top. Since that value (it's really a pointer) is non-null, the check for null never comes back as true.

*Jon Hanna 在评论中指出,对于 default(Nullable<T>),此语句不正确,这是正确的 - 装箱此值返回 null 对于任何T.

*Jon Hanna pointed out in a comment that this statement is not true for default(Nullable<T>) which is correct - boxing this value returns null for any T.

这篇关于检查 null 时,泛型函数是否将值类型隐式转换为对象?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆