以下是我所挣扎的简单案例:
public bool CompareStruct<S>(S a, S b) where S : struct
{
return a == b;
}
以上内容不会使用错误Operator '==' cannot be applied to operands of type 'S' and 'S'
进行编译。
通常情况下,我不会感到惊讶。但是我已经指出S
是一个结构 - 所以我为什么不能比较这两个参数?
我不认为this SO question在这里有任何相关性 - 毕竟,我使用的是struct
类型,而不是参考类型。
答案 0 :(得分:3)
这里的问题是C#中==
的默认行为是引用相等。结构中的引用相等没有意义,因为它总是返回false
。
编译器无法知道==
是否已被重载且S
具有值相等语义,因此不允许使用它。
要解决此问题,请使用Equals
,并考虑将S
限制为IEquatable<S>
,如果适当,以避免不必要的装箱操作。
答案 1 :(得分:2)
问题在于,当您指定泛型类型参数为struct
的约束时,即。 ValueType ,调用此方法的struct
没有必要为==
和!=
运算符提供重载实现,就像我们的自定义值类型一样定义它我们需要为它们提供==
和!=
运算符重载。
替代方法可以是使用Object.Equals
方法或在其自己的实例上调用Equals()
方法,如:
public bool CompareStruct<S>(S a, S b) where S : struct
{
return a.Equals(b);
}
或:
public bool CompareStruct<S>(S a, S b) where S : struct
{
return Object.Equals(a,b);
}
要记住的是,但是默认情况下,相等运算符不适用于值类型,除非您为该类型重载==
运算符,而使用==
运算符的引用类型则检查引用这是为什么将约束应用于class
的工作正常。
我曾写过一篇关于此的帖子,可能会有帮助,可以在this link (Equality Operator (==) and Value Types in C#)
阅读答案 2 :(得分:1)
除非明确覆盖var results = Regex.Matches(input, @"<PATTERN_HERE>")
.Cast<Match>()
.Select(m => m.Value)
.ToList();
和==
运算符,否则不能对用户定义的ValueType使用==
。这是因为!=
的默认实现不实现这些运算符。例如,下面没有编译:
struct
因此,如果您不能对已知结构执行此操作(默认情况下),那么除非您提供更多信息(例如,此结构必须包含更多信息),否则您无法对通用结构执行此操作(编译时已知的信息较少)实施struct Foo
{
}
void Main()
{
Foo f1;
Foo f2;
if(f1 == f2) // The compiler complains here
{
}
}
)
以上内容适用于类,因为它们在使用IEquatable<S>
时默认使用引用相等性。这不适用于值类型,因为它们是按值复制的。