Enumeration depending on type T

I have a generic class that should constrain an enum based on a specific type:

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 to depend on T 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 a class condition for this? I was thinking about interface, but enums don't inherit from interfaces.

+2


source to share


5 answers


If you create your field

public ValueType Operator { get; set; }

      

It will work, but I'm not sure if this is what you want ...



- Change

What are you trying to do, anyway? C # has operator overloading, so maybe this might be useful instead?

-1


source


There is no good way to do what you are trying to do without having something like:

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

      

This is really not very useful as you have to know in advance all the different possibilities for T.

What you can 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 IsMatch

? Or it displays the selected filter without actually implementing it.

If you do, things get a little more complicated ...

+1


source


Can the enum type just be another generic parameter, eg.

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

      

Perhaps you need more information, but not 100% sure how it would mean to actually match the code that will use it

0


source


You must specify the enum type as a template parameter.

public class Condition<TValue, TOperator> 
{
    public TValue Value { get; private set; }
    public TOperator Operator { get; private set; }

    private Condition(TValue val, TOperator op)
    {
        Value = val;
        Operator = op;
    }
}

      

It would be nice to add where TOperator : Enum

, but I'm pretty sure the compiler doesn't allow it.

0


source


Thanks for answers.

I wanted to avoid having more than one class, but apparently this is not possible. Based on the last comment from silky, I ended up in the same solution as nader. Not optimal, but it does the enum constraint trick, the con is that the client needs to know there are n classes:

public abstract class ConditionBase<T, E>
{
  public T Value { get; set; }
  public E Operator { get; set; }
  protected ConditionBase(T Value, E Operator)
  {
    this.Value = Value;
    this.Operator = Operator;
  }
}

public enum ConditionOperatorsString { None, Like, Equal }
public class ConditionString : ConditionBase<string, ConditionOperatorsString>
{
  public ConditionString(String Value, ConditionOperatorsString Operator) : base(Value, Operator) { }
}
public enum ConditionOperatorsDate { None, Like, BeforeThan, AfterThan }
public class ConditionDate : ConditionBase<DateTime?, ConditionOperatorsDate>
{
  public ConditionDate(DateTime? Value, ConditionOperatorsDate Operator) : base(Value, Operator) { }
}

      

Client Usage:

  ConditionString StrCond = new ConditionString(string.Empty, ConditionOperatorsString.None);
  ConditionDate DateCond = new ConditionDate(DateTime.MinValue, ConditionOperatorsDate.None);

      

I wanted to be able to use something like:

  ConditionGeneric StrCond = new ConditionGeneric(string.Empty, ConditionOperatorsString.None);
  ConditionGeneric DateCond = new ConditionGeneric(DateTime.MinValue, ConditionOperatorsDate.None);
  ConditionGeneric InvalidStrCond = new ConditionGeneric(string.Empty, ConditionOperatorsDate.None);
  ConditionGeneric InvalidDateCond = new ConditionGeneric(DateTime.MinValue, ConditionOperatorsString.None);

      

0


source







All Articles