我正在创建一个通用类来保存小部件,我在实现contains方法时遇到了麻烦:
public class WidgetBox<A,B,C>
{
public bool ContainsB(B b)
{
// Iterating thru a collection of B's
if( b == iteratorB ) // Compiler error.
...
}
}
错误:运算符'=='无法应用于'V'和'V'类型的操作数
如果我无法比较类型,我如何实现包含?字典,列表和所有其他通用容器如何做到这一点?
答案 0 :(得分:7)
这里有几个选项
第一种是使用Object.Equals
:
if(b.Equals(iteratorB)) {
// do stuff
}
小心使用此选项;如果B
未覆盖Object.Equals
,那么当B
是引用类型时,默认比较是引用相等,而B
是值类型时,值相等。这可能不是您正在寻求的行为,而且如果没有其他信息,我会考虑接下来的两个选项之一。
第二种是添加B
为IComparable
的约束:
public class WidgetBox<A, B, C> where B : IComparable
这样
if(b.CompareTo(iteratorB) == 0) {
// do stuff
}
第三个是要求IEqualityComparer<B>
传递给WidgetBox
的构造函数
public class WidgetBox<A, B, C> {
IEqualityComparer<B> _comparer;
public WidgetBox(IEqualityComparer<B> comparer) {
_comparer = comparer;
}
// details elided
}
然后:
if(_comparer.Equals(b, iteratorB)) {
// do stuff
}
使用最后一个选项,您可以提供默认为EqualityComparer<T>.Default
的重载:
public WidgetBox() : this(EqualityComparer<T>.Default) { }
答案 1 :(得分:3)
并非所有对象都实现==但所有对象都具有Equals(尽管它可以从Object.Equals继承)。
public class WidgetBox<A,B,C>
{
public bool ContainsB(B b)
{
// Iterating thru a collection of B's
if( b.Equals(iteratorB) )
...
}
}
答案 2 :(得分:3)
要添加到Jason的答案,您还可以添加where T : IEquatable<T>
而不是IComparable
。这提供了Equals
方法的重载,该方法接受T
参数。
public class WidgetBox<A,B,C> where B : IEquatable<B>
{
public bool ContainsB(B b)
{
// Iterating thru a collection of B's
if( b.Equals(iteratorB) )
...
}
}
这可能比仅使用提供的Object.Equals
方法更可取,因为它会检查两个对象引用的等价性(我相信),因此可能无法提供您想要的功能(例如,如果您希望具有相同Person
属性的两个SSN
对象被视为相等,或类似的东西。)
但是要回答你的问题“所有.NET集合是如何做到的”,我相信Equals
方法(没有约束)是你的答案。
答案 3 :(得分:2)
在编译时,无法保证类型参数B中的类型提供相等运算符。
相反,你可以这样做:
var comparer = EqualityComparer<B>.Default;
foreach (B item in items) {
if ( comparer.Equals(b, item) ) {
....
}
}
答案 4 :(得分:0)
if (b != null)
if (b.Equals(iteratorB))
...
答案 5 :(得分:0)
如果你可以在你的情况下侥幸逃脱,那么所需要的只是B
上的一个类约束public class WidgetBox<A,B,C> where B : class
将消除问题