views:

695

answers:

5

I've got the following generic class and the compiler complains that "Operator '!=' cannot be applied to operands of type 'TValue' and 'TValue'" (see CS0019):

public class Example<TValue>
{
    private TValue _value;
    public TValue Value
    {
        get { return _value; }
        set
        {
            if (_value != value) // <<-- ERROR
            {
                _value= value;
                OnPropertyChanged("Value");
            }
        }
    }
}

If I constrain TValue to class, I could use Object.Equals(). Since I need this for boths structs and classes I'd be very happy if I could avoid that though.

So the question is, how can I compare two elements of the same but unconstrained generic type for equality?

+2  A: 
  • Equals() for value types
  • ReferenceEquals() for reference types
leppie
I'd rather avoid having to reflect or otherwise distinguish the two cases. Currently I'm using an abstract base and implement these bits twice :-/
David Schmitt
What reflection are you using? Doing a typeof(TValue) is a compile time constant, and checking that type wont really cost anything.
leppie
+9  A: 

Did you try something like this?

public class Example<TValue>
{
    private TValue _value;
    public TValue Value
    {
        get { return _value; }
        set
        {

            if (!object.Equals(_value, value))
            {
                _value = value;
                OnPropertyChanged("Value");
            }
        }
    }
}
Sergiu Damian
http://msdn.microsoft.com/en-us/library/w4hkze5k.aspx says that by default value types will be compared bitwise, else the Equals() method is used. That's what I was looking for.
David Schmitt
Note that this will incur boxing penalties for value types.
Jon Skeet
A: 

I think the != operator cannot be applied here because there are cases where it can't be used. For instance, != can't be used for comparing structs, unless the compare operators (== !=) are overloaded.

Of course, you can compare language structs, like int != int, but I'm not sure how this is implemented.

So, because TValue can be a custom struct, it cannot use the != operator.

bruno conde
Yes, that was my understanding of CS0019 too.
David Schmitt
+1  A: 

Is IComparable an option?

public class Example<TValue> where TValue: IComparable
{
    private TValue _value;
    public TValue Value
    {
        get { return _value; }
        set
        {

            if (_value.CompareTo(value) != 0)
            {
                _value = value;
                OnPropertyChanged("Value");
            }
        }
    }
}
liggett78
+2  A: 

Three options:

  • Constrain TValue to implement IEquatable<TValue> and then call x.Equals(y)
  • Take another parameter of type IEqualityComparer<TValue> and use that
  • Use EqualityComparer<TValue>.Default to perform the comparisons

You could always mix and match options 2 and 3, of course - default to the default comparer, but also allow a specific one to be provided.

Jon Skeet