比较通用方法中的结构

时间:2017-06-29 10:19:56

标签: c# generics

以下是我所挣扎的简单案例:

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类型,而不是参考类型。

3 个答案:

答案 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>时默认使用引用相等性。这不适用于值类型,因为它们是按值复制的。