当前位置: 首页 > 知识库问答 >
问题:

泛型函数在检查NULL时是否隐式地将值类型强制转换为对象?

巩俊远
2023-03-14
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
int i = 0;
bool b = (object)i == null;

共有1个答案

翟俊哲
2023-03-14

xxbbcc的回答假设OP在问“为什么0不等于null”,这很可能就是问题的全部。另一方面,在泛型类型的上下文中,关于装箱的问题通常与泛型类型通过避免装箱而提供的性能优势有关。

在考虑这个问题时,IL可能会产生误导。它包括一个box指令,但这并不意味着实际上将在堆上分配值类型的box实例。IL“框”值,因为IL代码也是泛型的;用类型参数替换类型参数是JIT编译器的职责。对于不可为空的值类型,JIT编译器优化了用于装箱和检查结果的IL指令,因为它知道结果将始终是非空的。

我向示例代码添加了一个Thread.Sleep调用,以便有时间附加调试器。(如果在Visual Studio中使用F5启动调试器,即使是发布版本,也会禁用某些优化)。以下是发布版本中的机器代码:

            Thread.Sleep(20000);
00000000 55                   push        ebp 
00000001 8B EC                mov         ebp,esp 
00000003 83 EC 0C             sub         esp,0Ch 
00000006 89 4D FC             mov         dword ptr [ebp-4],ecx 
00000009 83 3D 04 0B 4E 00 00 cmp         dword ptr ds:[004E0B04h],0 
00000010 74 05                je          00000017 
00000012 E8 AD 4B 6A 71       call        716A4BC4 
00000017 33 D2                xor         edx,edx 
00000019 89 55 F4             mov         dword ptr [ebp-0Ch],edx 
0000001c 33 D2                xor         edx,edx 
0000001e 89 55 F8             mov         dword ptr [ebp-8],edx 
00000021 B9 C8 00 00 00       mov         ecx,0C8h 
00000026 E8 45 0E 63 70       call        70630E70 

            int i = 0;
0000002b 33 D2                xor         edx,edx 
0000002d 89 55 F8             mov         dword ptr [ebp-8],edx 
            IsNull(i);  // Works fine
00000030 8B 4D F8             mov         ecx,dword ptr [ebp-8] 
00000033 FF 15 E4 1B 4E 00    call        dword ptr ds:[004E1BE4h] 

            string s = null;
00000039 33 D2                xor         edx,edx 
0000003b 89 55 F4             mov         dword ptr [ebp-0Ch],edx 
            IsNull(s);  // Blows up
0000003e 8B 4D F4             mov         ecx,dword ptr [ebp-0Ch] 
00000041 BA 50 1C 4E 00       mov         edx,4E1C50h 
00000046 FF 15 24 1C 4E 00    call        dword ptr ds:[004E1C24h] 
        }
0000004c 90                   nop 
0000004d 8B E5                mov         esp,ebp 
0000004f 5D                   pop         ebp 
00000050 C3                   ret 
            if (obj == null)
00000000 55                   push        ebp 
00000001 8B EC                mov         ebp,esp 
00000003 83 EC 0C             sub         esp,0Ch 
00000006 33 C0                xor         eax,eax 
00000008 89 45 F8             mov         dword ptr [ebp-8],eax 
0000000b 89 45 F4             mov         dword ptr [ebp-0Ch],eax 
0000000e 89 4D FC             mov         dword ptr [ebp-4],ecx 
00000011 83 3D 04 0B 32 00 00 cmp         dword ptr ds:[00320B04h],0 
00000018 74 05                je          0000001F 
0000001a E8 ED 49 6E 71       call        716E4A0C 
0000001f B9 70 C7 A4 70       mov         ecx,70A4C770h 
00000024 E8 2F FA E9 FF       call        FFE9FA58 
00000029 89 45 F8             mov         dword ptr [ebp-8],eax 
0000002c 8B 45 F8             mov         eax,dword ptr [ebp-8] 
0000002f 8B 55 FC             mov         edx,dword ptr [ebp-4] 
00000032 89 50 04             mov         dword ptr [eax+4],edx 
00000035 8B 45 F8             mov         eax,dword ptr [ebp-8] 
00000038 85 C0                test        eax,eax 
0000003a 75 1D                jne         00000059 
                throw new NullReferenceException();
0000003c B9 98 33 A4 70       mov         ecx,70A43398h 
00000041 E8 12 FA E9 FF       call        FFE9FA58 
00000046 89 45 F4             mov         dword ptr [ebp-0Ch],eax 
00000049 8B 4D F4             mov         ecx,dword ptr [ebp-0Ch] 
0000004c E8 DF 22 65 70       call        70652330 
00000051 8B 4D F4             mov         ecx,dword ptr [ebp-0Ch] 
00000054 E8 BF 2A 57 71       call        71572B18 
        }
00000059 90                   nop 
0000005a 8B E5                mov         esp,ebp 
0000005c 5D                   pop         ebp 
0000005d C3                   ret 
            if (obj == null)
00000000 55                   push        ebp 
00000001 8B EC                mov         ebp,esp 
00000003 83 EC 0C             sub         esp,0Ch 
00000006 33 C0                xor         eax,eax 
00000008 89 45 F8             mov         dword ptr [ebp-8],eax 
0000000b 89 45 F4             mov         dword ptr [ebp-0Ch],eax 
0000000e 89 4D FC             mov         dword ptr [ebp-4],ecx 
00000011 83 3D 04 0B 32 00 00 cmp         dword ptr ds:[00320B04h],0 
00000018 74 05                je          0000001F 
0000001a E8 ED 49 6E 71       call        716E4A0C 
0000001f B9 70 C7 A4 70       mov         ecx,70A4C770h 
00000024 E8 2F FA E9 FF       call        FFE9FA58 
00000029 89 45 F8             mov         dword ptr [ebp-8],eax 
0000002c 8B 45 F8             mov         eax,dword ptr [ebp-8] 
0000002f 8B 55 FC             mov         edx,dword ptr [ebp-4] 
00000032 89 50 04             mov         dword ptr [eax+4],edx 
00000035 8B 45 F8             mov         eax,dword ptr [ebp-8] 
00000038 85 C0                test        eax,eax 
0000003a 75 1D                jne         00000059 
                throw new NullReferenceException();
0000003c B9 98 33 A4 70       mov         ecx,70A43398h 
00000041 E8 12 FA E9 FF       call        FFE9FA58 
00000046 89 45 F4             mov         dword ptr [ebp-0Ch],eax 
00000049 8B 4D F4             mov         ecx,dword ptr [ebp-0Ch] 
0000004c E8 DF 22 65 70       call        70652330 
00000051 8B 4D F4             mov         ecx,dword ptr [ebp-0Ch] 
00000054 E8 BF 2A 57 71       call        71572B18 
        }
00000059 90                   nop 
0000005a 8B E5                mov         esp,ebp 
0000005c 5D                   pop         ebp 
0000005d C3                   ret 
            Thread.Sleep(20000);
00000000 55                   push        ebp 
00000001 8B EC                mov         ebp,esp 
00000003 50                   push        eax 
00000004 B9 20 4E 00 00       mov         ecx,4E20h 
00000009 E8 6A 0C 67 71       call        71670C78 
            IsNull(s);  // Blows up
0000000e B9 98 33 A4 70       mov         ecx,70A43398h 
00000013 E8 6C 20 F9 FF       call        FFF92084 
00000018 89 45 FC             mov         dword ptr [ebp-4],eax 
0000001b 8B C8                mov         ecx,eax 
0000001d E8 66 49 6C 70       call        706C4988 
00000022 8B 4D FC             mov         ecx,dword ptr [ebp-4] 
00000025 E8 46 51 5E 71       call        715E5170 
0000002a CC                   int         3 
 类似资料:
  • 我有一个父类来处理我所有的自定义异常,父母异常。我希望所有的子异常都有一个方法来向异常添加消息。为了做到这一点,我创建了一个泛型方法,在向其添加消息后返回泛型类型的对象。我在父类方法中使用来添加消息,然后返回,但是由于该方法返回泛型类型,所以我将其转换为泛型类型T。这似乎是可行的,但是给出了警告。我的代码如下: 该行给出的警告是。这种方法似乎确实如预期的那样有效,所以我并不担心,但我想更好地理解为

  • 有没有一种简单的方法可以做到这一点: 编辑:我写了一份正确答案的工作副本:

  • 我在这里遇到了一个关于带列表的泛型有界类型的小问题。请帮帮我! 有什么方法可以克服这个问题,或者我可以安全地压制警告吗?

  • 问题内容: 让我们假设下表(例如,几个内部join语句的结果): 例如,您可以从以下语句中获取: 现在,如果我想将t1.column_1和t2.column_2总结如下 结果显示如下: 我的问题基本上是:有没有一种方法可以将NULL类型转换为0以便进行一些数学运算? 我曾尝试和,而是保持一个。 问题答案: 使用的列值转换到零。或者,COALESCE函数将执行相同的操作,除了(1)符合ANSI标准,

  • 我正在创建一个由数组支持的泛型类型堆栈。当我尝试创建泛型类型数组时,Java不允许我这样做。有人告诉我,我必须创建一个类型为Object的数组,并将其转换为泛型类型。我已经将对象数组转换为类型,但如何处理Java不断给我的未检查类型错误? 这就是我目前所处的位置。 更新:我正在创建一个对象数组,然后在方法的末尾将返回类型转换为T类型。

  • 此代码有效。它以“未检查或不安全操作”警告进行编译和运行。 当这两个给我运行时错误时 我遇到的错误如下: