4

我刚刚在 dotPeek,String.cs 中找到它:

[ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
[__DynamicallyInvokable]
public override bool Equals(object obj)
{
  if (this == null)
    throw new NullReferenceException();
  string strB = obj as string;
  if (strB == null)
    return false;
  if (object.ReferenceEquals((object) this, obj))
    return true;
  if (this.Length != strB.Length)
    return false;
  else
    return string.EqualsHelper(this, strB);
}

如果 this == null,则在第二行抛出 NullReferenceException。那么如何调用空对象的方法呢?

MSDN 说: 请注意,应用程序抛出 ArgumentNullException 异常,而不是这里讨论的 NullReferenceException 异常。

以下 Microsoft 中间语言 (MSIL) 指令引发 NullReferenceException:

callvirt
cpblk
cpobj
initblk
ldelem.<type>
ldelema
ldfld
ldflda
ldind.<type>
ldlen
stelem.<type>
stfld
stind.<type>
throw
unbox

如果我明白了,在进入方法体之前会抛出异常。正确的?那么需要从方法中抛出 NullReferenceException 吗?是否__DynamicallyInvokableAttribute强制方法被称为绕过任何检查?或者是其他东西?

谢谢。

4

1 回答 1

4

C# 确实使用 callvirt 在输入空对象之前获得 NullReferenceException 的地方。但是由于 BCL 是为过多的语言而设计的,因此它们确实在使用 call 指令的某些中心部分(例如字符串)中防止了空对象。

托管 C++ 是 call 指令最值得注意的用户。

这样做是为了帮助调试(据我所知),但它在整个 BCL 中根本不一致。

于 2012-10-20T06:06:45.630 回答