winforms 在C#中,是否可以声明一个属性,使其仅返回两种类型中的一种

yyhrrdl8  于 2022-11-17  发布在  C#
关注(0)|答案(2)|浏览(177)

我有一处房产(好吧,很多),我目前已经声明为对象,但是我希望能够将其限制为两种类型。例如,我希望一个属性要么接受bool,或包含表达式的类的示例,该表达式在使用它的上下文中将计算为布尔值(Expression类包含一个字符串表达式,它可以在运行时解析并计算为布尔值或错误)。同样,我可以对integer、double、DateTime等做类似的操作。
如何创建一个只接受一个值的属性,或者创建一个将生成该值的Expression类的示例?
我知道我可能会问一些C#本身不会做的事情,但是最接近的近似值是什么呢?
编辑:对于其他上下文,这些是正在使用winforms中的PropertyGrid编辑的对象属性,以便用户可以下拉选择{true/false/Expression}中的一个,其中Expression打开编辑表达式的对话框,或者用户可以直接将其键入PropertyGrid中。因此,拥有两个属性会破坏人体工程学,因为在用户看来,这将只是一个属性。

jei2mxaa

jei2mxaa1#

编辑:对于其他上下文,这些是正在使用winforms中的PropertyGrid编辑的对象属性,以便用户可以下拉选择{true/false/Expression}中的一个,其中Expression打开编辑表达式的对话框,或者用户可以直接将其键入PropertyGrid中。因此,拥有两个属性会破坏人体工程学,因为在用户看来,这将只是一个属性。
C#中的惯用解决方案是创建一个表示可能选择的专用类,例如

class UserChoice
{
     public bool? BooleanValue { get; }
     public Expression ExpressionValue { get; }

     // The factory methods ensure that exactly one of BooleanValue
     // and ExpressionValue is not null.

     public static FromBoolean(bool value) => new UserChoice(value, null);

     public static FromExpression(Expression expression)
     {
         if (expression is null)
         {
             throw new ArgumentNullException(nameof(expression));
         }
         return new UserChoice(null, expression);
     }
     
     private UserChoice(bool? booleanValue, Expression expressionValue)
     {
         BooleanValue = booleanValue;
         ExpressionValue = expressionValue;
     }
}

这将是基本结构。可能的改进包括:

  • FromBoolean返回静态UserChoice.TrueUserChoice.False字段现在,您可以对True/False值进行相等引用
  • Evaluate方法,传回布林值或评估运算式。
  • IsBooleanIsExpression便利属性。
62o28rlo

62o28rlo2#

从技术上讲,你可以通过implicit operator的帮助来实现这个行为(见下面的代码),但是你真的想要“两种类型”的属性吗?拥有 * 两 * 个属性不是更好的设计吗?

// Class that evaluates to bool
public class MyBoolClass {

  // Stab class which evaluates to constant bool
  public class MyBoolClassStub : MyBoolClass {
    internal MyBoolClassStub(bool value) {
      Value = value;
    }

    public bool Value { get; }

    public override bool ToBool() => Value;
  }

  // Stub class which returns true whenever evaluates to bool
  public static MyBoolClassStub EverTrue { get; } = new MyBoolClassStub(true);

  // Stub class which returns flase whenever evaluates to bool
  public static MyBoolClassStub EverFalse { get; } = new MyBoolClassStub(false);

  public virtual bool ToBool() {
    //TODO: here we evaluate to bool; put relevant code
  }

  public static implicit operator bool(MyBoolClass value) =>
    value?.ToBool() ?? throw new ArgumentNullException(nameof(value)); 

  public static implicit operator MyBoolClass(bool value) =>
    value ? EverTrue : EverFalse;
}

有了这样一个类声明,你可以如下声明属性:

private MyBoolClass m_MyProperty;

public MyBoolClass MyProperty {
  get {
    if (m_MyProperty is null)
      return false; //TODO: default value here

    return m_MyProperty;
  }
  set {
    m_MyProperty = value;
  }
}

并使用它

// We can assign bool (which will be turned into Stub class)
MyProperty = true;

// We can read bool
if (MyProperty)
  Console.WriteLine("true");

// We can assign "class evaluated to bool"
MyProperty = new MyClass();

Console.WriteLine(MyProperty ? "yes" : "no");

相关问题