Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why do I need to implement IComparable<T> to compare two values in generic method?

I am wondering why the code like this won't work:

public static bool cmp <T> (T a, T b)
{
    return a == b;
}

I assume, that there should be an IComparable constraint added, to make it work (maybe CompareTo instead of == as well). With class constraint, references would be compared. With struct constraint, no comparison is allowed, as well as with no constraint.

Wouldn't it be possible to resolve given type and compare references in case when object is passed, and compare values when the value types are passed?

like image 511
Bart Juriewicz Avatar asked Aug 12 '14 08:08

Bart Juriewicz


People also ask

What is IComparable in C#?

C# provides an IComparable interface. This interface provides different types of type-specific comparison methods which means a value type or a class can implement this interface to sort its instances because we cannot sort the instances of a class directly because the compiler does not know on which basis to sort.

How do you compare T types?

If you need to compare objects of type T by more or less, then the IComparable<T> interface will do. Such a comparison is necessary, for example, when sorting. If you need to compare objects of type T for equality/inequality, you can use the IEquatable<T> interface.


1 Answers

There is a remark in the language specification.

Take a look at paragraph 7.10.6:

The predefined reference type equality operators do not permit value type operands to be compared. Therefore, unless a struct type declares its own equality operators, it is not possible to compare values of that struct type.

Structs cannot be compared with ==, because this operator is not defined for every value type.

The standard explicitly mentions integer types, floats, decimals, booleans and enumerations, and of course reference types.

So it is not possible by design. And why?

It makes sense. Intuition tells us that a value type should be compared by value. So two value type variables are equal, if they have the same content. Although a struct is a blob of data, it may contain references to objects. If this references differ, but have the same value, what should be the result of such a comparison?

For example:

public struct A
{
    public string S;
}

A a;
A b;
a.S = "Hello";
b.S = "Hello world".Split(' ')[0]; //to avoid reusing the same reference, probably ;]
var result = (a == b);

What should be the answer? Binary they are different, but values are the same.

There is always ValueType.Equals, overloaded from object.Equals, that tries to address this problem. It performs the value comparison where possible and reference comparison where not. But you have to keep in mind, that it makes a struct kinda bloated. You have a default operation on every struct, that could take ages to complete. So it is possible, but not as a struct's functionality per se.

like image 121
Piotr Zierhoffer Avatar answered Sep 25 '22 16:09

Piotr Zierhoffer