C# C语言中的设计问题:泛型还是多态性?

C# C语言中的设计问题:泛型还是多态性?,c#,generics,polymorphism,C#,Generics,Polymorphism,我需要一些设计方面的帮助。我努力做到的是: 我有一个叫做Document的主类。此类具有属性类的列表。这些属性类有一些共同的属性,比如Identity和Name,但它们在一个我称之为Value的属性上有所不同。每个不同的属性类的值类型都不同,类型为string、integer、List、DateTime、float、List以及由多个属性组成的类。一个例子是我称之为PairAttribute的类,它有两个属性:Title和Description 我试图实现的是属性子类的Value属性的类型安全性

我需要一些设计方面的帮助。我努力做到的是:

我有一个叫做Document的主类。此类具有属性类的列表。这些属性类有一些共同的属性,比如Identity和Name,但它们在一个我称之为Value的属性上有所不同。每个不同的属性类的值类型都不同,类型为string、integer、List、DateTime、float、List以及由多个属性组成的类。一个例子是我称之为PairAttribute的类,它有两个属性:Title和Description

我试图实现的是属性子类的Value属性的类型安全性,并且这些子类应该能够添加到文档类的属性列表中。我本可以只创建一个属性类,该属性类具有object类型的Value属性,并且可以使用它来完成,但这正是我在这里试图避免的

公共属性Identity和Name应该放在基类中,我想,让我们称之为AttributeBase类。但是我想有一个子类,比如StringAttribute,其中Value属性是string类型,IntegerAttribute类中Value属性是Integer类型,StringListAttribute中Value属性是List类型,PairAttribute类中Value是具有多个属性的类,等等


你知道我该如何实现这一点吗?这是一个解决方案,我应该去在所有或它是一个更好的方式来解决这种类型的安全问题?我希望通过代码示例进行澄清:

您不需要指定语言,但是Java和C使用的术语泛型描述的功能在其他语言中,如ML和Haskell中经常被调用。相反,Java和C中的共同含义实际上更精确地称为

关键是,无论您使用的是子类型多态性还是参数多态性,您的问题都需要多态性,因此我认为您走在了正确的轨道上

问题实际上归结为:参数多态性何时比子类型多态性更好?答案其实很简单:当它需要你写更少的代码时


所以,我建议您对这两种方法进行原型化,然后看看哪一种方法会导致更简单、更容易理解的代码。然后这样做。

您不需要指定语言,但是Java和C使用的术语泛型描述的特性在其他语言(如ML和Haskell)中经常被调用。相反,Java和C中的共同含义实际上更精确地称为

关键是,无论您使用的是子类型多态性还是参数多态性,您的问题都需要多态性,因此我认为您走在了正确的轨道上

问题实际上归结为:参数多态性何时比子类型多态性更好?答案其实很简单:当它需要你写更少的代码时


所以,我建议您对这两种方法进行原型化,然后看看哪一种方法会导致更简单、更容易理解的代码。然后这样做。

您可以使用泛型属性而不是继承/方法多态性进行传递,但您需要将它们存储在某个列表中,为此您需要一个接口,因为.Net中的数据存储不能是未定义泛型类型的集合,如果您要定义它们,则无法在其中混合类型:

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

        }
    }
TretObject实际上不改变类型,它只对T进行装箱,Tret不使用中间变量就取消装箱。如果在调用GetValue时错过了正确的类型,这当然会失败。即使发送了兼容的类型,比如Value is integer,并且您执行GetValue->,因为不允许将整数取消装箱到double中

装箱/取消装箱的速度不如强制转换快,但它确保了类型安全性得到保护,据我所知,在编译时已知的接口中,无法以其他方式使用泛型


所以这应该是类型安全的。。。没有太多的代码。

您可以使用泛型属性而不是继承/方法多态性进行传递,但您需要将它们存储在某个列表中,为此您需要一个接口,因为.Net中的数据存储不能是未定义泛型类型的集合,如果要定义它们,则无法在其中混合类型:

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

        }
    }
TretObject实际上不改变类型,它只对T进行装箱,Tret不使用中间变量就取消装箱。如果在调用GetValue时错过了正确的类型,这当然会失败。即使发送了兼容的类型,比如Value is integer,并且您执行GetValue->,因为不允许将整数取消装箱到double中

装箱/取消装箱的速度不如强制转换快,但它确保了类型安全性得到保护,据我所知,在编译时已知的接口中,无法以其他方式使用泛型

所以这应该是类型安全的。。。而且没有很多代码