2

Let say I have the following class:

public sealed class ScaleValue : 
    IComparable, IComparable<ScaleValue>, IEquatable<ScaleValue>
{
    public double Value
    { get; set;}
    public string Definition
    { get; set;}

    // interface methods
    ...
}

If I want to make my class comparable to a double should I just include IComparable<double> and implement it that way or do I have to do it another way?

And when I want my class to be comparable to doubles should the double.CompareTo give the same result as the ScaleValue.CompareTo?

and how about Equals?

I think I put the responsibilities wrong in my design. I think my best option is to make a Scale class with a ContainsValue(double Value) method. This way I can look up the value and keep the responsibilities where they are needed.

Heretic Monkey
  • 11,687
  • 7
  • 53
  • 122
  • The problem here is that comparable check will no longer be symmetric. someScaleValue.CompareTo(1.2) will return a value, but `1.2.CompareTo(someScaleValue)` will throw an exception, because the `double` version of comparability won't know how to handle your type. That's...a problem. – Servy Oct 07 '13 at 18:19
  • 1
    You already have a double there, just compare that (remember the KISS principle) – Alex Oct 08 '13 at 09:19
  • Why would you want your class to be comparable to doubles? Are you trying to make a static method? You already have IComparable implemented. In the Comparer method, you can compare the ScaleValue.Value member.. – Ren Oct 08 '13 at 09:31

2 Answers2

0

What your class is comparable to is up to you. You could make it comparable to anything, as the non-generic version of the IComparable interface takes an object; in the implementation of CompareTo method, you can basically sniff the type of the object (unless it is null).

When you use the generic version of IComparable<T>, you're making the statement that you implement a strongly-typed comparison method to whatever the type parameter T is.

Generally, if you have an IComparable<T> implementation for one type, you probably should have an IEquatable<T> implementation as well.

Having an IComparable/IComparable<T> implementation means that what is being represented by the structure has a natural ordering to it. Ordering also implies that there can be equality between two instances: if instance a of T is not greater than or less than instance b of T then it must be equal.

To that end, if you implement IComparable/IComparable<T>, then logic dictates that you implement IEquatable/IEquatable<T>.

Of course, when you implement IEquatable/IEquatable<T>, you should override Equals and GetHashCode.

Which in turn means that you should override all the comparison operators:

  • == (which implies !=)
  • < and <=
  • > and >=
casperOne
  • 73,706
  • 19
  • 184
  • 253
  • what you told me i already figured out. what my point is that i have a set of ScaleValue's name `Scale`. now i want to check if some value `a` of the type `double` is in the list. `Scale.contains(a)`. that is why i asked if i should implement `Icomparable`. in the ScaleValue class the definition propertie is less important. – user2038134 Oct 06 '13 at 18:22
  • @user2038134 That makes no sense. What if you have two properties that expose `double`? One implementation of `IComparable` wouldn't give you what you're looking for. You need to use something like the `Where` extension method in LINQ to do what you want. – casperOne Oct 07 '13 at 04:16
0

You cannot compare objects in a collection to an object of different type using contains method unless you implement a whole new collection type for your class or using some sort of extension method!!!

Omid S
  • 181
  • 1
  • 7