Mark
Mark

Reputation: 9438

Generic constraints: Can I test Equality of generic that can be a reference or value type?

I want a single generic class that can accept either reference or value types, and only perform an action based on an equality test. consider the following:

public class Property<TProp>
  where TProp : struct, IEquatable<TProp>
{
   public TProp Value;

   public void SetValue(ObservableObject owner, TProp value)
   {
      if (!Value.Equals(value))     // cannot use != on struct constrained TProp
      {
          // ... set the property
      }
   }
}

public class ByRefProperty<TProp>
  where TProp : class   // Dont want to require IEquatable<> on reference type TProp
{
   public TProp Value;

   public void SetValue(ObservableObject owner, TProp value)
   {
      if (Value != value)           
      {
          // ... set the property
      }
   }
}

I'm having to use generic constraints and two classes to be able to test value type equality vs reference type equality. Is there any way around this so that I end up with just one class?

I don't particularly want a solution that involves boxing value types, using reflection, or run-time IL generation. Is there a simple solution that I've missed here?

Upvotes: 11

Views: 2507

Answers (1)

Jon Skeet
Jon Skeet

Reputation: 1504052

The best way do to this is generally EqualityComparer<T>.Default:

public void SetValue(ObservableObject owner, TProp value)
{
   if (!EqualityComparer<TProp>.Default.Equals(Value, value))
   {
       // ... set the property
   }
}

Note that this even handles null values for you in the logical way (null is equal to null but nothing else).

Upvotes: 16

Related Questions