我需要一个带有属性的基类,我可以使用相同的属性但不同(兼容)类型派生类。基类可以是抽象的。
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>();
//...
}
}
我尝试使用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
//...
}
}
答案 0 :(得分: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);
}
}
基本上我在中间添加了一个通用类,用于存储正确类型的属性。假设您永远不需要从迭代Prop
成员的代码中访问List<Base>
,这将有效。 (您可以随时向名为Base
的{{1}}添加一个抽象方法,如果需要,可以将泛型强制转换为对象。)
样本用法:
GetProp
编辑:添加了GetProp()方法,以说明如何从基类直接访问该属性。
答案 1 :(得分:6)
您无法覆盖属性的类型。看看下面的代码:
StrBase s = new StrBase();
Base b = s;
这是完全有效的代码。但是当你尝试这样做时会发生什么?
b.prop = 5;
整数可以转换为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;
这是因为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;
}
}
}
}
您还可以在子类中公开类型安全的属性:
public class StrBase : Base
{
public string strProp {
get
{
return (string)this.prop;
}
set
{
this.prop = value;
}
}
}
答案 2 :(得分:1)
我也面临着这个问题,但是我找到了一种无需泛型类型的优雅方法。
我已经在此处撰写了有关此主题的完整文章: http://materiagame.com/2019/09/04/override-property-type-in-a-derived-class
TheUncas21
答案 3 :(得分:0)
public class first
{
private int someV;
public virtual object SomeV { get => someV; set => someV = (int)value; }
public first() { }
}
public class two : first
{
private string someV;
public override object SomeV { get => someV; set => someV = value.ToString(); }
public two() { }
}
及其使用:
first firstClass = new first();
firstClass.SomeV = 1;
two twoClass = new two();
twoClass.SomeV = "abcd";