枚举取决于类型 T

发布于 2024-08-03 12:24:00 字数 742 浏览 3 评论 0原文

我有一个泛型类,需要根据定义的类型限制枚举:

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;
  }
}

现在的问题是我希望运算符类型依赖于 T,所以何时:

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

我如何定义类条件?我想到了一个接口,但枚举不继承自接口。

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.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

溺孤伤于心 2024-08-10 12:24:00

如果没有在构造函数中执行以下操作,就没有什么好方法可以完成您想要做的事情:

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

这确实不是很有用,因为您必须提前知道 T 的所有不同可能性。

可以这样做,是这样的:

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)
    {
    }
}

然后你可以声明

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

你需要有一个IsMatch吗?或者这是为了显示选定的过滤器,而不实际实现它。

如果你这样做,事情就会变得更加复杂......

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...

睫毛溺水了 2024-08-10 12:24:00

枚举类型是否只是另一个泛型参数,例如

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;
  }
}

可能需要更多信息,但不能 100% 确定这实际上如何适合使用它的代码

Could the enum type just be another generic parameter e.g.

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;
  }
}

Might need more info though, not 100% sure how this is meant to actually fit in with the code that will make use of it

怎言笑 2024-08-10 12:24:00

您应该包含枚举类型作为模板参数。

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;
    }
}

如果能够添加 where TOperator : Enum 那就太好了,但我很确定编译器不允许这样做。

You should include 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 be able to add where TOperator : Enum, but I'm pretty sure the compiler doesn't allow that.

似最初 2024-08-10 12:24:00

感谢您的回答。

我想避免上不止一堂课,但显然这是不可能的。根据 Silky 的最后评论,我得到了与 nader 类似的解决方案。
不是最佳的,但它确实限制了枚举,缺点是客户端必须知道有 n 个类:

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) { }
}

客户端使用:

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

我希望能够从客户端使用类似的内容:

  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);

Thanks for the answers.

I wanted to avoid to have more than one class but apparently it cannot be done. Based on the last comment from silky i got to a similar sollution as nader.
Not the optimal one but it does the trick of restricting the enum, the con is that the client has to be aware that 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 use:

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

I wanted to be able to use from the client 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);
悲念泪 2024-08-10 12:24:00

如果你让你的领域

public ValueType Operator { get; set; }

变得可行,但我不确定这是否是你想要的......

- 编辑

你到底想做什么? C# 具有运算符重载,所以也许这可能有用?

If you make your field

public ValueType Operator { get; set; }

It'll work, but I'm not sure if that's what you want ...

-- Edit

What are you trying to do, anyway? C# has operator overloading, so perhaps that could be of use, instead?

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文