JJo*_*oos 8 .net c# generics .net-3.5
我刚遇到这种情况,我认为这是一个使用default关键字的好机会.但它没有编译,我想不出为什么.以下示例说明了我的问题:
public class Test<TDataSource>
{
public IQueryable<TDataSource> DataSource { get; set; }
public bool GetOneOrDefaultResult()
{
var result = DataSource.SingleOrDefault();
return result != default(TDataSource);
}
}
Run Code Online (Sandbox Code Playgroud)
你会在第8行得到一个错误("运算符'=='不能应用于'TDataSource'和'TDataSource'类型的操作数.").我认为使用default关键字将消除引用类型和值类型之间的任何比较问题.
添加将TDataSource限制为引用类型的通用约束使得这段代码可以编译.
有人可以解释为什么编译器不会为我解决这个问题吗?只是不够聪明才能看到这会起作用吗?
这是相关的: 不能将operator ==应用于C#中的泛型类型?
[编辑] SLaks的答案给了我一些灵感,'=='运算符不起作用,但Equals函数应该.
public class Test<TDataSource>
{
public IQueryable<TDataSource> DataSource { get; set; }
public bool GetOneOrDefaultResult()
{
var result = DataSource.SingleOrDefault();
return result.Equals(default(TDataSource));
}
}
Run Code Online (Sandbox Code Playgroud)
这个编译会正常吗?
您不能假设每个值类型都会覆盖==运算符.(即使他们这样做了,也无法使用泛型来调用它;它是一种静态方法)
相反,你应该写
return !(ReferenceEquals((object)result, (object)default(TDataSource))
|| result.Equals(default(TDataSource)));
Run Code Online (Sandbox Code Playgroud)
如果result是null(和引用类型),则ReferenceEquals调用将返回true,因此Equals不会被调用并且不会抛出NullReferenceException.
如果TDataSource是值类型,ReferenceEquals则将比较两个不同的盒装引用(可能恰好包含相同的值,但仍然不同),因此它将传递给Equals调用.