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
i.e. 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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With