c#中的设计问题:泛型或多态性或两者兼而有之
本文关键字:多态性 兼而有之 泛型 问题 | 更新日期: 2023-09-27 17:53:55
我需要一些帮助,我有一个设计问题。我想实现的是:
我有一个名为Document的主类。这个类有一个属性类的列表。这些属性类有一些共同的属性,如Identity和Name,但它们在一个我称为Value的属性上有所不同。对于每个不同的属性类,值类型是不同的,可以是字符串、整数、列表、日期时间、浮点数、列表以及由几个属性组成的类。一个例子是类PairAttribute,它有两个属性:Title和Description。
我试图实现的是Attribute子类的Value属性的类型安全,并且这些子类应该能够添加到Document类中的Attribute列表中。我本可以只创建一个具有object类型的Value属性的Attribute类,但这正是我在这里要避免的。
公共属性(身份和名称)应该放在一个基类中,我猜,我们叫它AttributeBase类。但我想有一个子类,说StringAttribute,其中的值属性是类型字符串,一个IntegerAttribute类,其中的值属性是类型Integer,一个StringListAttribute,其中的值属性是类型列表,一个PairAttribute类,其中的值是一个类与几个属性,等
你知道我怎么实现这个吗?这是一个解决方案,我应该去还是它是一个更好的方法来解决这种类型的安全问题?我将欣赏代码示例来澄清:)
您不指定语言,但是术语"泛型"(如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>();
}
}
(Tret)(Object)实际上不改变类型,它只是将T框起来,而(Tret)在不使用中间变量的情况下将值打开。如果在调用GetValue<type>()
时错过了正确的类型,这当然会失败。即使发送的是兼容类型,如Value is integer,并且您执行GetValue<double>()
->,因为不允许将整数拆箱成双精度类型。
装箱/拆箱不如强制类型转换快,但它确保了类型安全,而且据我所知,没有其他方法可以将泛型与编译时已知的接口一起使用。
所以这应该是类型安全的…而且不需要很多代码