在没有泛型类约束的情况下,将泛型类型与其默认值进行比较,会产生编译时错误
Posted
技术标签:
【中文标题】在没有泛型类约束的情况下,将泛型类型与其默认值进行比较,会产生编译时错误【英文标题】:Comparison of a generic type with its default value, without a generic class constraint, gives a compile time error 【发布时间】:2011-04-07 20:44:03 【问题描述】:我刚遇到这种情况,我认为这是使用默认关键字的好机会。但它没有编译,我想不出为什么。下面的例子说明了我的问题:
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));
这样编译能正确运行吗?
【问题讨论】:
如果你只是想弄清楚是否有结果,那你就错了,因为你无法区分没有结果和结果为 0。 Gabe函数的逻辑只是一个例子,没有用处。 您的编辑可能会引发 NullReferenceExeption。您需要调用静态的Equals(a, b)
方法。
Null or default comparison of generic argument in C#的可能重复
【参考方案1】:
您不能假设每种值类型都会覆盖==
运算符。 (即使他们这样做了,也无法使用泛型来调用它;这是一个静态方法)
相反,你应该写
return !(ReferenceEquals((object)result, (object)default(TDataSource))
|| result.Equals(default(TDataSource)));
如果result
是null
(和引用类型),则ReferenceEquals
调用将返回true
,因此Equals
不会被调用,也不会抛出NullReferenceException
。
如果TDataSource
是一个值类型,ReferenceEquals
将比较两个不同的加框引用(可能恰好包含相同的值,但仍然不同),因此它将传递给Equals
调用。
【讨论】:
请注意,一般来说,这是您必须比较两个未知类型的值是否相等的方法。 (即这不仅仅适用于查找默认值) 你说得对。这只是不覆盖“==”运算符的用户定义结构吗? @JJoos,如果值类型覆盖==
运算符,则认为最佳做法是覆盖 Equals()
以使其行为相同。这不是严格保证的,但如果我发现一个不以这种方式运行的值类型,我会认为这是一个错误。
不需要这么复杂的东西,你只需要使用静态 Object.Equals 方法:Equals(result, default(TDataSource))
。
@Thomas Levesque,是的,在@SLaks 发帖后也想到了这一点。似乎工作正常并且更具可读性。以上是关于在没有泛型类约束的情况下,将泛型类型与其默认值进行比较,会产生编译时错误的主要内容,如果未能解决你的问题,请参考以下文章
Kotlin泛型总结 ★ ( 泛型类 | 泛型参数 | 泛型函数 | 多泛型参数 | 泛型类型约束 | 可变参数结合泛型 | out 协变 | in 逆变 | reified 检查泛型参数类型 )