使用不同的兼容类型覆盖属性
我需要一个具有属性的基类,在其中我可以派生具有相同属性但不同(兼容)类型的类。基类可以是抽象的。
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>();
//...
}
}
我尝试使用泛型,但这在使用该类时给我带来了问题,因为我想在列表中存储不同类型的基类。
public class BaseG<T>
{
public T prop { get; set; }
}
public class UseIt
{
public void use()
{
List<BaseG> l = new List<BaseG>(); // requires type argument
//...
}
}
I need a base class with a property where I can derive classes with the same property but different (compatible) types. The base Class can be abstract.
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>();
//...
}
}
I tried it with Generics but that gives me a problem when using the class, because I want to store differently typed base classes in the 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
//...
}
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
这是建议的解决方案的另一种方法:
基本上,我在中间添加了一个通用类,用于存储正确类型的属性。假设您永远不需要从迭代
List
成员的代码中访问Prop
,这将起作用。 (您始终可以向Base
添加一个名为GetProp
的抽象方法,如果需要,该方法将泛型强制转换为对象。)示例用法:
编辑:添加了 GetProp() 方法来说明如何从基类直接访问属性。
Here's an alternative approach to proposed solution:
Basically I've added a generic class in the middle that stores your properly-typed property. this will work assuming that you never need to access
Prop
from the code that iterates the members of theList<Base>
. (You could always add an abstract method toBase
calledGetProp
that casts the generic to an object if that's required.)Sample usage:
Edit: Added the GetProp() method to illustrate how the property can be directly accessed from the base class.
您无法覆盖属性的类型。看一下下面的代码:
这是完全有效的代码。但是当你尝试这样做时会发生什么?
整数可以转换为
object
,因为一切都是从object
派生的。但由于b
实际上是一个StrBase
实例,因此它必须以某种方式将整数转换为字符串,但它不能。这就是为什么您不允许覆盖该类型的原因。同样的原则也适用于泛型:
这是因为 C# 2.0 中的泛型类型是不变的。 C# 4.0 确实允许这种类型的转换,称为协变和逆变。
解决方案
一个选项是在需要时将
对象
强制转换回字符串。您可以在子类中添加类型验证:您还可以在子类中公开类型安全的属性:
You can't override the type of a property. Take a look at the following code:
This is completely valid code. But what happens when you try to do this?
The integer can be converted to
object
, because everything is derived fromobject
. But sinceb
is actually aStrBase
instance, it would have to convert the integer to a string somehow, which it can't. So that is why you aren't allowed to override the type.The same principle applies to generics:
This is because generic types in C# 2.0 are invariant. C# 4.0 does allow this type of conversions, called covariance and contravariance.
Solutions
An option is to cast the
object
back to string when you need it. You could add type validation in the subclass:You could also expose a type-safe property in the subclass:
从C# 9.0开始,这是可能的
(请参阅Microsoft 文档)
This is possible since C# 9.0
(see Microsoft docs)
以及它们的使用:
and use of those: