C# – enum depending on Type T

cenumsgenerics

I have a generic class that needs to limit an enum depending on the type defined:

public enum ConditionOperatorsString { None, Like, Equal }
public enum ConditionOperatorsDate { None, Equal, BeforeThan, AfterThan }
public class Condition<T>
{
  public T Value { get; set; }
  public ConditionOperatorsString Operator { get; set; }
  public Condition(T Value, ConditionOperatorsString Operator)
  {
    this.Value = Value;
    this.Operator = Operator;
  }
}

Now the problem is that i want the Operator type be dependant on T so when:

Condition<string> CStr= new Condition<string>(string.Empty, ConditionOperatorsString.None)
Condition<DateTime> CStr= new Condition<DateTime>(DateTime.Now, ConditionOperatorsDate.None)

How do I define the class Condition for that? I thought of an interface but enums don't inherit from interfaces.

Best Answer

There's no good way to do what you're trying to do without having, in your constructor something like:

if (typeof(T) == typeof(string) && 
    typeof(Operator) != typeof(ConditionOperatorsString))
{ 
    throw new Exception("Invalid conditionoperators value);
}

That's really not very useful, since you have to know, ahead of time, all the different possibilities for T.

What you could do, is something like this:

public abstract class ComparableBase<T,K>
{
    public T Value { get; protected set; }
    public K ConditionOperator { get; protected set; }
    // public abstract bool IsMatch(T other); // Is this required?

    protected ComparableBase(T value, K op)
    {
        this.Value = value;
        this.ConditionOperator = op;
    }
}

public enum ComparableOperator { None, Equal, Less, Greater }

public enum LikeOrEqualOperator { None, Like, Equal }

public class ComparableCondition<T> : ComparableBase<T,ComparableOperator>
{
    public ComparableCondition(T value, ComparableOperator op):base(value, op)
    {
    }
}

public class LikeOrEqualCondition<T> : ComparableBase<T, LikeOrEqualOperator>
{
    public LikeOrEqualCondition(T value, LikeOrEqualOperator op):base(value, op)
    {
    }
}

then you can declare

var condition1 = new LikeOrEqualCondition<string>("hi", LikeOrEqualOperator.Equal);

Do you need to have an IsMatch? Or is this to display the selected filter, without actually implementing it.

If you do, things are a teensy bit more complicated...