将泛型与可能是值或引用类型的 null 进行比较?
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 不抱怨)。尽管我确实想知道:
- 是否有更标准的方法来处理这种情况?
- 这是否有可能引发问题?
- 当我进行调用并传入值类型时,幕后到底发生了什么?
public void DoFoo<T>(T foo) where T : ISomeInterface<T>
{
//possible compare of value type with 'null'.
if (foo == null) throw new ArgumentNullException("foo");
}
I'm purposely only checking against null because I don't want to restrict a ValueType
from being equal to its default(T)
. My code compiles and works just fine this way (ReSharper complains, but not CodeAnalysis). Though I do wonder:
- Is there a more standard way to handle this situation?
- 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?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
不,不会有任何问题,但如果您希望警告消失,您可以使用以下命令:
或者您可以执行以下操作:
No, there won't be any problems, but if you want the warning to disappear, you can use the following:
Alternatively you can do something like this:
这是一个很好的见解,但不要'不用担心,您已经被覆盖了。首先使用
==
将 T 与default(T)
进行比较是不合法的;重载解析不会找到唯一的最佳==
运算符。当然,您可以与
.Equals
进行比较,但是如果接收器为空,您就会面临崩溃的风险,这正是您试图避免的。不。与 null 进行比较是正确的做法。
正如 C# 规范在第 7.10.6 节中所述:“即使 T 可以表示值类型,x == null 构造也是允许的,并且当 T 时结果简单地定义为 false是一个值类型。”
当然。仅仅因为代码可以编译并不意味着它具有您想要的语义。写一些测试。
这个问题是模棱两可的。让我把它改写成两个问题:
抖动会在第一次调用时使用该构造来编译该方法。当抖动检测到 null 检查时,它会将其替换为“false”,因为它知道任何不可为 null 的值类型都不会等于 null。
在这种情况下,抖动无法消除空检查,并且调用站点无法避免装箱。 SFoo 实例将被装箱,并且将检查对装箱的 SFoo 的引用是否为 null。
That is a good insight, but don't worry, you are already covered there. It is not legal to compare a T against
default(T)
using==
in the first place; overload resolution will not find a unique best==
operator.Of course, you could do the comparison with
.Equals
but then you run the risk of crashing if the receiver is null, which is precisely what you are attempting to avoid.No. Comparing to null is the right thing to do here.
As the C# specification says in section 7.10.6: "The
x == null
construct is permitted even though T could represent a value type, and the result is simply defined to be false when T is a value type."Sure. Just because code compiles does not mean that it has the semantics you intend. Write some tests.
The question is ambiguous. Let me rephrase it into two questions:
The jitter compiles the method on the first invocation with that construction. When the jitter detects the null check, it replaces it with "false" because it knows that no non-nullable value type will ever be equal to null.
In that case the jitter cannot elide the null check and the call site cannot avoid the boxing. The SFoo instance will be boxed, and the reference to the boxed SFoo will be checked to see if it is null.