简体   繁体   中英

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' .

Normally, I wouldn't be surprised. But I've indicated that S is a struct - so why can't I compare the two parameters?

I don't think this SO question has any relevancy here - after all, I'm working with struct types, not reference types.

The problem here is that the default behavior of == in C# is reference equality. Reference equality in structs makes no sense because it will always return false .

The compiler has no way of knowing if == has been overloaded and S has value equality semantics and therefore disallows its use.

To get around this, use Equals and consider constraining S to IEquatable<S> if appropiate to avoid unnecessary boxing operations.

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.

An alternate can be to use Object.Equals method or call the Equals() method on it's own instance like:

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.

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#)

You can't use == on user-defined ValueTypes unless you explicitly override the == and != operators. This is because the default implementation for a struct doesn't implement these operators. 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> )

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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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