Rai*_*erM 18 c# generics inheritance properties .net-2.0
我需要一个带有属性的基类,在这里我可以派生具有相同属性但不同(兼容)类型的类.基类可以是抽象的.
public class Base
{
public virtual object prop { get; set; }
}
public class StrBase : Base
{
public override string prop { get; set; } // compiler error
}
public class UseIt
{
public void use()
{
List<Base> l = new List<Base>();
//...
}
}
Run Code Online (Sandbox Code Playgroud)
我尝试使用Generics但是在使用该类时会给我一个问题,因为我想在List中存储不同类型的基类.
public class BaseG<T>
{
public T prop { get; set; }
}
public class UseIt
{
public void use()
{
List<BaseG> l = new List<BaseG>(); // requires type argument
//...
}
}
Run Code Online (Sandbox Code Playgroud)
And*_*son 26
这是建议解决方案的另一种方法:
public abstract class Base
{
public abstract void Use();
public abstract object GetProp();
}
public abstract class GenericBase<T> : Base
{
public T Prop { get; set; }
public override object GetProp()
{
return Prop;
}
}
public class StrBase : GenericBase<string>
{
public override void Use()
{
Console.WriteLine("Using string: {0}", Prop);
}
}
public class IntBase : GenericBase<int>
{
public override void Use()
{
Console.WriteLine("Using int: {0}", Prop);
}
}
Run Code Online (Sandbox Code Playgroud)
基本上我在中间添加了一个通用类,用于存储正确类型的属性.假设您永远不需要Prop从迭代成员的代码访问,这将工作List<Base>.(你总是可以添加一个抽象的方法Base称为GetProp如果这是要求蒙上通用的对象.)
样品用法:
class Program
{
static void Main(string[] args)
{
List<Base> l = new List<Base>();
l.Add(new StrBase {Prop = "foo"});
l.Add(new IntBase {Prop = 42});
Console.WriteLine("Using each item");
foreach (var o in l)
{
o.Use();
}
Console.WriteLine("Done");
Console.ReadKey();
}
}
Run Code Online (Sandbox Code Playgroud)
编辑:添加了GetProp()方法,以说明如何从基类直接访问该属性.
您无法覆盖属性的类型.看看下面的代码:
StrBase s = new StrBase();
Base b = s;
Run Code Online (Sandbox Code Playgroud)
这是完全有效的代码.但是当你尝试这样做时会发生什么?
b.prop = 5;
Run Code Online (Sandbox Code Playgroud)
整数可以转换为object,因为一切都是从中派生的object.但由于b实际上是一个StrBase实例,它必须以某种方式将整数转换为字符串,但它不能.这就是为什么不允许您覆盖该类型的原因.
同样的原则适用于泛型:
List<BaseG<object>> l = new List<BaseG<object>>();
BaseG<string> s = new BaseG<string>();
// The compiler will not allow this.
l.add(s);
// Here's the same problem, convert integer to string?
BaseG<object> o = l[0];
o.prop = 5;
Run Code Online (Sandbox Code Playgroud)
这是因为C#2.0中的泛型类型是不变的.C#4.0确实允许这种类型的转换,称为协方差和逆变.
解决方案
一个选项是object在需要时将背面强制转换为字符串.您可以在子类中添加类型验证:
public class StrBase : Base
{
private string propValue;
public override object prop {
get
{
return this.propValue;
}
set
{
if (value is string)
{
this.propValue = (string)value;
}
}
}
}
Run Code Online (Sandbox Code Playgroud)
您还可以在子类中公开类型安全的属性:
public class StrBase : Base
{
public string strProp {
get
{
return (string)this.prop;
}
set
{
this.prop = value;
}
}
}
Run Code Online (Sandbox Code Playgroud)