C#如何避免对子类进行类型转换?
假设我有一个叫做Shape的基类。然后是一些子类,如圆形和方形 然后,让我们在另一个名为GetShape的类中创建一个方法:C#如何避免对子类进行类型转换?,c#,.net,subtyping,C#,.net,Subtyping,假设我有一个叫做Shape的基类。然后是一些子类,如圆形和方形 然后,让我们在另一个名为GetShape的类中创建一个方法: public Shape GetShape() { return new Circle(); } 好的,我的想法是,我可以传入一个shapeType,然后返回一个强类型的Shape子类。上面的例子是对实际代码的大规模简化,但我认为它能理解问题的关键 那么当我调用这个方法时,它会是什么样子呢 var shapeCreator = new ShapeCreato
public Shape GetShape()
{
return new Circle();
}
好的,我的想法是,我可以传入一个shapeType,然后返回一个强类型的Shape子类。上面的例子是对实际代码的大规模简化,但我认为它能理解问题的关键
那么当我调用这个方法时,它会是什么样子呢
var shapeCreator = new ShapeCreator();
Circle myCircle = shapeCreator.GetShape();
唯一的问题是它甚至不会运行,因为它需要一个演员阵容
这实际上是可行的:
Circle myCircle = (Circle) shapeCreator.GetShape();
我对这种类型转换不感兴趣,我如何避免它,并且仍然实现一种让方法返回基类的方法,这样我就可以返回任何兼容的子类 如果你想做某件事
Circle
-特定,你必须强制转换到这个特定类型
您可以使用对象,但在这种情况下,您会丢失编译阶段的类型安全检查。您可以使用方法调用传递所需的类型。在方法中,可以使用该方法创建要传递的类型的对象
GetShape定义
public T GetShape(),其中T:Shape
{
return(T)Activator.CreateInstance(typeof(T));
}
GetShape的调用
Circle c=GetShape();
矩形r=GetShape();
编辑您可以使用
将新约束应用于泛型类时的类型参数
创建该类型的新实例,如下例所示:
public T GetShape(),其中T:Shape,new()
{
返回新的T();
}
没有办法解决您的问题。但是你说
因此,我的想法是,我可以通过一个形状类型,然后得到一个
返回的类型化形状子类
你的意思是这样的:
var shape = shapecreator.GetShape(typeof(Circle));
或
如果类型不是静态已知的,但只能在运行时确定,则需要逻辑来决定调用哪个方法,例如使用If
或switch
语句。也就是说,演员阵容也需要这样的逻辑,所以这不是真正的缺点
另一种选择可能是使用抽象工厂设计模式,其中您有一个
ShapeFactoryBase
类和一个virtualshapecreate()
方法,以及一个派生类CircleFactory
,该类继承自该类,并重写Create()
方法。但是,您仍然需要强制转换,并且您仍然需要逻辑来决定强制转换到什么类型。您可以使用泛型来实现这一点,即使没有反射。此示例在T
上使用无参数构造函数过滤器(示例由Adil更改):
public T GetShape(),其中T:Shape,new()
{
返回新的T();
}
无需使用函数,只需将形状类嵌套在GetShape
静态类中,并根据需要从该静态类创建新形状即可
public static class GetShape {
public class Circle() { .. }
public class Square() { .. }
public class Triangle() { .. }
...
}
var NewShape = new GetShape.Circle();
但是,如果你不想这样做,我建议你使用泛型。@Jodrell:如果你不介意的话,因为你删除了你的答案:我从你的答案中添加了
Shape,
在t
的过滤器中。是的,但是shapeCreator.GetShape()
比new Circle()
有什么好处呢?即使是从泛型方法调用它作为shapeCreator.GetShape()
,这怎么比new T()
更好呢?@Kris:它的当前形式没有什么,但是如果该方法可以进行更多的泛型初始化,这是一个不错的解决方案。
public T GetShape<T>() where T : Shape, new()
{
return new T();
}
var shape = shapecreator.GetShape(typeof(Circle));
var shape = shapecreator.GetShape<Circle>();
var circle = shapecreator.GetCircle();
public T GetShape<T>() where T : Shape, new()
{
return new T();
}
public static class GetShape {
public class Circle() { .. }
public class Square() { .. }
public class Triangle() { .. }
...
}
var NewShape = new GetShape.Circle();