考虑我正在审核的以下代码:
public override bool Equals(object other)
{
return !object.ReferenceEquals(null, this)
&& (object.ReferenceEquals(this, other)
|| ((other is MyType) && this.InternalEquals((MyType)other)));
}
此代码中的第一行引发了我的好奇心。每当this
为null时,该方法应返回false。现在我非常确定程序员打算用!object.ReferenceEquals(other, null)
编写null
来快捷方式,但是他坚持认为this
可以为空。我坚持认为它不能(除非有人使用直接内存操作)。我们应该留下吗?
答案 0 :(得分:7)
虽然我当然不会通常检查this
的无效性,但是可能,没有任何实际的记忆肮脏 - 只是一点反思:
using System;
public class Test
{
public void CheckThisForNullity()
{
Console.WriteLine("Is this null? {0}", this == null);
}
static void Main(string[] args)
{
var method = typeof(Test).GetMethod("CheckThisForNullity");
var openDelegate = (Action<Test>) Delegate.CreateDelegate(
typeof(Action<Test>), method);
openDelegate(null);
}
}
或者,生成使用call
而不是callvirt
来调用null目标上的实例方法的IL。完全合法,而不是C#编译器通常会做的事情。
这与终结无关,终结本身就是毛茸茸但却以不同的方式。如果CLR可以证明你不会使用实例中的任何字段(我强烈希望包含{{1),那么在实例方法执行时可以运行终结器。参考)。
至于提供的代码 - 不,这看起来只是一个错误。我会把它重写为:
this
...假设public override bool Equals(object other)
{
return Equals(other as MyType);
}
public bool Equals(MyType other)
{
if (ReferenceEquals(other, null))
{
return false;
}
// Now perform the equality check
}
是一个类,而不是一个结构。请注意我如何使用具有正确参数类型的其他 public 方法 - 我同时实现MyType
。
答案 1 :(得分:1)
C#通常不允许在null
上调用方法。我认为编写该程序员的程序员要么来自C ++背景(我认为方法可以在null
上调用,只要他们不访问this
的数据成员)或写作对于特殊情况(例如通过反思调用,如已经说过的那样)的防御性。