Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/272.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 尝试访问子类成员时使用泛型_C#_.net_Generics - Fatal编程技术网

C# 尝试访问子类成员时使用泛型

C# 尝试访问子类成员时使用泛型,c#,.net,generics,C#,.net,Generics,我有这些物品: 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 { dou

我有这些物品:

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
}
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
}
private DoSomething(T顺序),其中T:order
{
double myValue=订单是订单A | |订单是订单B?(T)订单.X:(T)订单.Y;
//多做点什么
}
但是我无法编译我的代码,因为“t不包含X的定义…”
这可能吗?

由于
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
}

由于
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
}
这将有助于:

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
}
然后,您可能希望将“做更多的事情”封装在私有方法中,以尽可能多地使用公共逻辑

或者,您可以按
顺序创建虚拟或抽象方法,如下所示:

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
}
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
}
注意,这两种解决方案都不需要使用泛型

这将起作用:

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
}
然后,您可能希望将“做更多的事情”封装在私有方法中,以尽可能多地使用公共逻辑

或者,您可以按
顺序创建虚拟或抽象方法,如下所示:

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
}
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
}

注意,这两种解决方案都不需要使用泛型

按顺序类定义一个抽象方法并在每个子类中重写它。这样,每个类都可以在不强制转换订单实例的情况下完成任务。正如@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();
}
如果处理更复杂,我建议您坚持使用模板方法模式:

按顺序类定义一个抽象方法,并在每个子类中重写它。这样,每个类都可以在不强制转换订单实例的情况下完成任务。正如@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();
}
如果处理更复杂,我建议您坚持使用模板方法模式:

我绝对赞成第二种方法,因为多态性正是拥有这些
Order
子类的好处。如果OP在
Order
类上添加
GetValue
方法,那么他在子类IMHO上保留
X
Y
属性是毫无意义的。@Crono可能是真的。目前还不清楚这些人在那里做什么,因为OP并没有提供一个非常清楚的问题描述。很可能它可以被重构,使得
Value
只是
Order
的一个属性,根本不需要重写。还有,为什么你建议重载
DoSomething
方法和可重写的
GetValue
方法?还是我遗漏了什么?@Crono我建议两种选择。这两种方法都是有效的我绝对赞成第二种方法,因为多态性正是拥有这些
Order
子类的好处。如果OP在
Order
类上添加
GetValue
方法,那么他在子类IMHO上保留
X
Y
属性是毫无意义的。@Crono可能是真的。目前还不清楚这些人在那里做什么,因为OP并没有提供一个非常清楚的问题描述。很可能它可以被重构,使得
Value
只是
Order
的一个属性,根本不需要重写。还有,为什么你建议重载
DoSomething
方法和可重写的
GetValue
方法?还是我遗漏了什么?@Crono我建议两种选择。这两种方法都是有效的。