C#如何避免对子类进行类型转换?

C#如何避免对子类进行类型转换?,c#,.net,subtyping,C#,.net,Subtyping,假设我有一个叫做Shape的基类。然后是一些子类,如圆形和方形 然后,让我们在另一个名为GetShape的类中创建一个方法: public Shape GetShape() { return new Circle(); } 好的,我的想法是,我可以传入一个shapeType,然后返回一个强类型的Shape子类。上面的例子是对实际代码的大规模简化,但我认为它能理解问题的关键 那么当我调用这个方法时,它会是什么样子呢 var shapeCreator = new ShapeCreato

假设我有一个叫做Shape的基类。然后是一些子类,如圆形和方形

然后,让我们在另一个名为GetShape的类中创建一个方法:

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();