public void DoFoo<T>(T foo) where T : ISomeInterface<T>
{
//possible compare of value type with 'null'.
if (foo == null) throw new ArgumentNullException("foo");
}
我故意只检查 null,因为我不想限制 ValueType
等于它的 default(T)
。我的代码以这种方式编译和工作得很好(ReSharper 提示,但 CodeAnalysis 没有)。虽然我确实想知道:
- 是否有更标准的方法来处理这种情况?
- 是否有可能由此引发问题?
- 当我调用并传入一个值类型时,幕后到底发生了什么?
最佳答案
I'm purposely only checking against
null
because I don't want to restrict a ValueType from being equal to itsdefault(T)
这是一个很好的见解,但别担心,您已经了解了这些内容。首先使用 ==
将 T 与 default(T)
进行比较是不合法的;重载解析不会找到唯一的最佳 ==
运算符。
当然,您可以使用 .Equals
进行比较,但是如果接收者为空,您将面临崩溃的风险,这正是您试图避免的。
Is there a more standard way to handle this situation?
没有。与 null 进行比较是正确的做法。
正如 C# 规范在第 7.10.6 节中所说:“x == null
构造是允许的,即使 T 可以表示值类型,并且结果被简单地定义为当 T 是值类型时为 false。"
Is there any chance of an issue arrising from this?
当然。仅仅因为代码编译并不意味着它具有您想要的语义。编写一些测试。
What truly happens under the hood when I make a call and pass in a value type?
这个问题是模棱两可的。让我改写成两个问题:
What truly happens under the hood when I make a call on the generic method with a type argument that is a non-nullable value type?
抖动会在第一次调用该构造时编译方法。当抖动检测到 null 检查时,它会将其替换为“false”,因为它知道任何不可为 null 的值类型都不会等于 null。
What truly happens under the hood when I make a call on the generic method with a type argument that is a reference type but an argument that is a struct type? For example:
interface IFoo : ISomeInterface<IFoo> {}
struct SFoo : IFoo { whatever }
...
DoFooInternal<IFoo>(new SFoo());
在那种情况下,抖动无法避免空值检查,调用站点也无法避免装箱。 SFoo 实例将被装箱,并且将检查对装箱 SFoo 的引用以查看它是否为空。
关于c# - 将泛型与可能是值或引用类型的 null 进行比较?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8823239/