views:

170

answers:

1

I have some generic types, like the following:

public struct Tuple<T1, T2> { ... }
public struct Tuple<T1, T2, T3> { ... }
etc.

These should in theory be able to compare themselves against other values of the same type, so that I can write the following type of code:

List<Tuple<Type, String>> l = new List<Tuple<Type, String>>();
l.Add(new Tuple<Type, String>(typeof(ISomeInterface), "123"));
if (l.Contains(new Tuple<Type, String>(typeof(ISomeOtherInterface), "123"))
    ...

unfortunately, there was a bug in my code, and the question then becomes how to do this correctly.

The bug had to do with my implementation of CompareTo>, which basically looks like this:

Int32 result = HelperMethods.CompareTwoFields<T1>(_Value1, other._Value1);
if (result != 0)
    return result;

Int32 result = HelperMethods.CompareTwoFields<T2>(_Value2, other._Value2);
if (result != 0)
    return result;

return 0;

HelperMethods.CompareTwoFields looks like this:

internal static Int32 CompareTwoFields<T>(T field1, T field2)
{
    Int32 result = 0;
    if (ReferenceEquals(field1, null) != ReferenceEquals(field2, null))
        result = ReferenceEquals(field1, null) ? -1 : +1;
    else if (!ReferenceEquals(field1, null) && field1 is IComparable<T>)
        result = ((IComparable<T>)field1).CompareTo(field2);
    else if (!typeof(T).IsValueType)
    {
        if (Object.ReferenceEquals(field1, field2))
            return 0;
        else
            return field1.ToString().CompareTo(field2.ToString());
    }
    return result;
}

The last if-statement there is something I tucked on now to fix the bug, but is this correct?

Basically, how do I compare two Type objects? Is there a meaningful comparison for these, except just to convert them to a string and compare?

+5  A: 

Do you mean:

bool equal = EqualityComparer<T>.Default.Equals(val1,val2);

This works with IEquatable<T> (for T : IEquatable<T>), else falls back to object.Equals.

There is also Comparer<T>.Default for inequality comparisons (greater/less):

int delta = Comparer<T>.Default.Compare(val1,val2);

This uses T : IComparable<T>, or T : IComparable otherwise.

By the way, Type should just use the regular reference compare provided by object.Equals, so it should just work fine with the above.

Marc Gravell
Ok, so that works for checking if they're equal. The question then is how I would change IComparer<Tuple<T1, T2>> so that it had some meaning for types not implementing IComparable, since all i can see with EqualityComparer is if they're equal, not their ordering... Perhaps I'm being too generic?
Lasse V. Karlsen
If the types don't have any notion of IComparable[<T>], then you'll need to provide an IComparer[<T>].
Marc Gravell