簡體   English   中英

C# 中的設計問題:Generics 或多態性或兩者兼而有之?

[英]Design issue in C#: Generics or polymorphism or both?

我需要一些幫助來解決我遇到的設計問題。 我試圖實現的是:

我有一個名為 Document 的主要 class。 這個 Class 有一個屬性類列表。 這些 Attribute 類有一些共同的屬性,例如 Identity 和 Name,但它們的不同之處在於我稱之為 Value 的一個屬性。 每個不同的屬性 class 的值類型是不同的,並且類型為字符串、integer、List、DateTime、float、List 以及由多個屬性組成的類。 一個例子是 class,我會調用 PairAttribute,它有 2 個屬性:標題和描述。

我試圖實現的是 Attribute 子類的 Value 屬性的類型安全,並且這些子類應該能夠添加到 Document class 中的 Attribute 列表中。 我本可以只制作一個屬性 class ,它的 Value 屬性類型為 object 並完成它,但這正是我在這里試圖避免的。

我猜公共屬性(身份和名稱)應該放在基礎 class 中,我們稱之為 AttributeBase class。 But I want to have a child class, say StringAttribute, where the Value property is of type string, a IntegerAttribute class where the Value property is of type Integer, a StringListAttribute where the Value property is of type List, a PairAttribute class where the Value是一個 class 具有多個屬性等

你知道我該如何實現嗎? 這是我應該 go 的解決方案,還是解決此類安全問題的更好方法? 我將不勝感激代碼示例以進行澄清:)

您無需指定語言,但術語“泛型”(如 Java 和 C# 所使用)所描述的特性在其他語言(如 ML 和 Haskell)中通常稱為“參數多態性”。 反之,Java和C#中“ 多態性”的常見含義,其實更准確地稱為“亞型多態性”。

關鍵是,無論您使用的是子類型多態性還是參數多態性,無論哪種方式,您的問題都需要多態性,所以我認為您走在正確的軌道上。

這個問題真正歸結為:參數多態性何時比子類型多態性更好? 答案其實很簡單:當它要求你編寫更少的代碼時。

所以,我建議你對這兩種方法都進行原型設計,然后看看哪一種會導致更簡單、更容易理解的代碼。 然后就這樣做。

您可以使用泛型屬性而不是繼承/方法多態性傳遞,但您需要將它們存儲在某個列表中,為此您需要一個接口,因為.Net 中的數據存儲不能是未定義泛型類型的 collections,如果您將定義它們,您將無法在其中混合類型:

    public interface IAttribute {
        string Identity { get; set; }
        string Name { get; set; }
        T GetValue<T>();
    }

    public class Attribute<T> : IAttribute
    {

        public string Identity { get; set; }
        public string Name { get; set; }
        public T Value { get; set; }
        public Tret GetValue<Tret>() {
            return (Tret)(Object)Value;
        }
    }

    static class Program
    {
        /// <summary>
        /// The main entry point for the application.
        /// </summary>
        [STAThread]
        static void Main()
        {
            List<IAttribute> lst = new List<IAttribute>();
            Attribute<string> attr1 = new Attribute<string>();
            attr1.Value = "test";

            Attribute<int> attr2 = new Attribute<int>();
            attr2.Value = 2;

            lst.Add(attr1);
            lst.Add(attr2);

            string attr1val = lst[0].GetValue<string>();
            int attr2val = lst[1].GetValue<int>();

        }
    }

(Tret)(Object) 實際上並沒有改變類型,它只是將 T 和 (Tret) 拆箱而不使用中間變量。 如果您在調用GetValue<type>()時錯過了正確的類型,這當然會失敗。 即使發送兼容類型,例如 Value is integer 並且您執行GetValue<double>() -> 因為將 integer 拆箱成雙精度是不允許的。

裝箱/拆箱不如強制轉換快,但它確保保留類型安全,並且據我所知,無法以其他方式將 generics 與編譯時已知接口一起使用。

所以這應該是類型安全的......並且沒有很多代碼。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM