泛型类型与其默认值的比较(没有泛型类约束)会产生编译时错误

时间:2010-09-03 13:29:36

标签: c# .net generics .net-3.5

我刚遇到这种情况,我认为这是一个使用默认关键字的好机会。但它没有编译,我想不出为什么。下面的例子说明了我的问题:

public class Test<TDataSource>
{
    public IQueryable<TDataSource> DataSource { get; set; }

    public bool GetOneOrDefaultResult()
    {
        var result = DataSource.SingleOrDefault();
        return result != default(TDataSource);
    }
}

第8行会出现错误(“运算符'=='不能应用于'TDataSource'和'TDataSource'类型的操作数。”)。我认为使用default关键字将消除引用类型和值类型之间的任何比较问题。

添加限制TDataSource到引用类型的通用约束使这段代码编译。

有人可以解释为什么编译器不能解决这个问题吗?只是不够聪明才能看到它会起作用吗?

这是相关的: Can't operator == be applied to generic types in 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));
    }
}

这个编译会正常运行吗?

1 个答案:

答案 0 :(得分:6)

您不能假设每种值类型都会覆盖==运算符。 (即使他们这样做了,也无法使用泛型来调用它;它是一种静态方法)

相反,你应该写

    return !(ReferenceEquals((object)result, (object)default(TDataSource)) 
          || result.Equals(default(TDataSource)));

如果resultnull(以及引荐类型),则ReferenceEquals来电将返回true,因此Equals将不会被调用并赢得不要扔NullReferenceException 如果TDataSource是值类型,ReferenceEquals将比较两个不同的盒装引用(可能恰好包含相同的值,但仍然不同),因此它将传递给{{1调用。