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;
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类型。
此代码有效。它以“未检查或不安全操作”警告进行编译和运行。 当这两个给我运行时错误时 我遇到的错误如下: