简体   繁体   English

比较通用方法中的结构

[英]Comparing structs in a generic method

Here's a simplified case of what I'm struggling with: 这是我正在努力解决的一个简化案例:

public bool CompareStruct<S>(S a, S b) where S : struct
{
  return a == b;
}

The above will not compile with the error Operator '==' cannot be applied to operands of type 'S' and 'S' . 以上不会编译错误Operator '==' cannot be applied to operands of type 'S' and 'S'

Normally, I wouldn't be surprised. 通常情况下,我不会感到惊讶。 But I've indicated that S is a struct - so why can't I compare the two parameters? 但我已经指出S是一个结构 - 所以为什么我不能比较这两个参数?

I don't think this SO question has any relevancy here - after all, I'm working with struct types, not reference types. 我不认为这个问题在这里有任何相关性 - 毕竟,我正在使用struct类型,而不是引用类型。

The problem here is that the default behavior of == in C# is reference equality. 这里的问题是C#中==的默认行为是引用相等。 Reference equality in structs makes no sense because it will always return false . 结构中的引用相等没有意义,因为它总是返回false

The compiler has no way of knowing if == has been overloaded and S has value equality semantics and therefore disallows its use. 编译器无法知道==是否已经过载并且S具有值相等语义,因此不允许使用它。

To get around this, use Equals and consider constraining S to IEquatable<S> if appropiate to avoid unnecessary boxing operations. 要解决这个问题,请使用Equals并考虑将S限制为IEquatable<S>如果适当的话,以避免不必要的装箱操作。

The problem is that when you specify the constraint that the generic type parameter is struct ie ValueType , it is not necessary that the struct which calls this method has provided the overload implementation for == and != operator for it, as for custom value types, when we define it we need to provide the == and != operator overloads for them to be used. 问题是,当您指定泛型类型参数为struct 即ValueType)的约束时,调用此方法的struct不必为其提供==!=运算符的重载实现,就像自定义值类型一样,当我们定义它时,我们需要为它们提供==!=运算符重载。

An alternate can be to use Object.Equals method or call the Equals() method on it's own instance like: 替代方法可以是使用Object.Equals方法或在其自己的实例上调用Equals()方法,如:

public bool CompareStruct<S>(S a, S b) where S : struct
{
  return a.Equals(b);
}

or: 要么:

public bool CompareStruct<S>(S a, S b) where S : struct
{
  return Object.Equals(a,b);
}

The point to remember is that but the equality operator is by default not available for value types unless you overload the == operator for that type and for reference types using == operator does is checking for reference equality so that's why applying constraint to class works fine. 需要记住的是,但是默认情况下,相等运算符不适用于值类型,除非您为该类型重载==运算符,并且使用==运算符确实引用类型正在检查引用相等性,这就是为什么将约束应用于class工作原理精细。

I once wrote a post about this which might be helpful which can be read at this link (Equality Operator (==) and Value Types in C#) 我曾写过一篇关于这个的帖子,可能会有用,可以在这个链接上读取(Equality Operator(==)和C#中的Value Types)

You can't use == on user-defined ValueTypes unless you explicitly override the == and != operators. 除非明确覆盖==!=运算符,否则不能对用户定义的ValueType使用== This is because the default implementation for a struct doesn't implement these operators. 这是因为一个默认的实现struct没有实现这些操作符。 For instance, the below doesn't compile: 例如,下面没有编译:

struct Foo
{

}

void Main()
{
    Foo f1;
    Foo f2;

    if(f1 == f2) // The compiler complains here
    {

    }
}

So if you can't do that for known structs (by default), then you can't do that for generic structs (less information known at compile time) unless you provide more information (for example that this struct have to implement IEquatable<S> ) 因此,如果您不能对已知结构执行此操作(默认情况下),那么除非您提供更多信息(例如,此结构必须实现IEquatable<S> ,否则您不能对通用结构执行此操作(编译时已知的信息较少)) IEquatable<S>

The above would work for classes because they uses reference equality by default when using == . 以上内容适用于类,因为它们在使用==时默认使用引用相等性。 That doesn't apply to Value Types because they are copied by value. 这不适用于值类型,因为它们是按值复制的。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM