在尝试访问子类成员时使用泛型
本文关键字:泛型 成员 子类 访问 | 更新日期: 2023-09-27 17:50:36
我有这些对象:
class Order { ... }
class OrderA : Order { public double X; }
class OrderB : Order { public double X; }
class OrderC : Order { public double Y; }
我想做一个方法来接收Order对象的3个子类中的任何一个,像这样:
private DoSomething<T>(T order) where T : Order
{
double myValue = order is OrderA || order is OrderB ? (T)order.X : (T)order.Y;
// DO SOMETHING MORE
}
但是我不能编译我的代码,因为"T不包含X的定义…"这可能吗?
这样可以:
double myValue =
(order is OrderA) ? ((OrderA)order).X :
(order is OrderB) ? ((OrderB)order).X :
(order is OrderC) ? ((OrderC)order).Y;
然而,在泛型中进行这种测试,有点违背了使用泛型的目的。
您可以提供不同的DoSomething
过载来处理您期望接收的每种情况:
private DoSomething(OrderA order)
{
double myValue = order.X;
// DO SOMETHING MORE
}
private DoSomething(OrderB order)
{
double myValue = order.X;
// DO SOMETHING MORE
}
private DoSomething(OrderC order)
{
double myValue = order.Y;
// DO SOMETHING MORE
}
那么你可能会想要把"DO SOMETHING MORE"封装在一个私有方法中,以使用尽可能多的公共逻辑。
或者,您可以在Order
中创建一个虚拟或抽象方法,如下所示:
class Order {
public virtual double GetValue() { ... }
}
class OrderA : Order {
public double X;
public override double GetValue() { return this.X; }
}
class OrderB : Order {
public double X;
public override double GetValue() { return this.X; }
}
class OrderC : Order {
public double Y;
public override double GetValue() { return this.Y; }
}
...
private DoSomething(Order order)
{
double myValue = order.GetValue();
// DO SOMETHING MORE
}
注意,两种解决方案都不需要使用泛型。
由于X
/Y
成员没有在核心Order
类中声明,因此DoSomething
方法不可能看到它们。当然,您可以将order值转换为您想要的类型,但这违背了开始使用泛型方法的目的。
我个人对泛型有一个经验法则:每当我需要对泛型类型进行强制转换时,我肯定做错了什么。
如果你所需要的只是在做"更多的事情"之前获得适当的值,我建议你使用重载方法代替。这些可以反过来调用带有适当参数的"核心"方法:
private void DoSomething(OrderA order)
{
DoSomethingMore(order, order.X);
}
private void DoSomething(OrderB order)
{
DoSomethingMore(order, order.X);
}
private void DoSomething(OrderC order)
{
DoSomethingMore(order, order.Y);
}
private void DoSomethingMore(Order order, double value)
{
// do something more
}
In Order类定义一个抽象方法,并在每个子类中重写它。这样,每个类都可以在不强制转换订单实例的情况下完成这项工作。正如@Crono所说,这将破坏泛型的目的。
//In Order class
public abstract void DoIt(){}
//In OrderSubClass class
public override void DoIt(){
//Do Something with X or Y
}
//Client code
private void doSomething( Order theOrder){
theOrder.DoIt();
}
如果处理更复杂,我建议您坚持使用模板方法模式:
模板方法模式