繁体   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