我有一個屬性(嗯,很多),我目前已將其宣告為物件,但我希望能夠將其限制為兩種型別。例如,我想要一個屬性,該屬性將采用布林值,或者包含一個運算式的類的實體,該運算式將在使用它的背景關系中計算為布林值(運算式類包括一個字串運算式,它可以在運行時決議并評估為布林值或錯誤)。同樣,我可能會對整數、雙精度、日期時間等做類似的事情。
我怎樣才能創建一個只接受一個值或將產生該值的 Expression 類的實體的屬性?
我知道我可能會問一些 C# 本身不會做的事情,但最接近的近似值是什么?
編輯:對于其他背景關系,這些是正在使用 winforms 中的 PropertyGrid 編輯的物件的屬性,以便用戶可以下拉選擇 {true/false/Expression} 之一,其中 Expression 打開一個用于編輯運算式的對話框,或者用戶可以直接在 PropertyGrid 中鍵入它。出于這個原因,擁有兩個屬性會破壞人體工程學,因為在用戶的心目中它只是一個。
uj5u.com熱心網友回復:
編輯:對于其他背景關系,這些是正在使用 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;
}
}
這將是基本結構。可能的改進是:
- 由 . 回傳的靜態
UserChoice.True
和UserChoice.False
欄位FromBoolean
。您現在有了 True/False 值的參考相等性。 Evaluate
回傳布林值或計算運算式的方法。IsBoolean
和IsExpression
便利屬性。
uj5u.com熱心網友回復:
從技術上講,您可以借助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");
轉載請註明出處,本文鏈接:https://www.uj5u.com/yidong/506811.html