C#如何避免类型转换为子类?

时间:2014-05-30 09:59:35

标签: c# .net subtyping

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

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

public Shape GetShape()
{
    return new Circle();  
}

好吧,我的想法是,我可以传入一个shapeType,然后返回一个强类型的Shape子类。上面的例子是对实际代码的大规模简化,但我认为它得到了重点。

那么当我调用这个方法时,它看起来像

var shapeCreator = new ShapeCreator();
Circle myCircle = shapeCreator.GetShape(); 

只有问题是它甚至无法运行,因为它需要演员。

这实际上有效:

Circle myCircle = (Circle) shapeCreator.GetShape(); 

我对这个演员阵容并不狂热,我怎么能避免它,并且仍然有办法让一个方法返回一个基类,这样我就可以返回任何兼容的子类。

5 个答案:

答案 0 :(得分:5)

即使没有反射,您也可以使用泛型。此示例使用T上的无参数构造函数过滤器(从Adil更改的样本):

public T GetShape<T>() where T : Shape, new()
{
    return new T();
}

答案 1 :(得分:3)

没有办法解决您提出的问题。但是,你说

  

所以我的想法是,我可以传入一个shapeType,然后强烈地获取   返回类型化的Shape子类

你的意思是这样的:

var shape = shapecreator.GetShape(typeof(Circle));

var shape = shapecreator.GetShape<Circle>();

如果是这样,并且在编译时静态知道类型,只需执行

var circle = shapecreator.GetCircle();

如果类型不是静态知道的,但只能在运行时确定,则需要逻辑来决定调用哪种方法,例如:使用ifswitch语句。话虽这么说,你也需要像演员这样的逻辑,所以这不是一个真正的劣势。

另一种选择可能是使用抽象工厂设计模式,其中ShapeFactoryBase类具有virtual Shape Create()方法,而派生类CircleFactory从中继承,并覆盖Create()方法。你仍然需要演员,你仍然需要逻辑来决定要演员的类型。

答案 2 :(得分:1)

您可以使用generic methods通过方法调用传递所需的类型。在该方法中,您可以使用Activator.Createinstance来创建要传递的类型的对象。

GetShape定义

public T GetShape<T>() where T : Shape
{
    return (T)Activator.CreateInstance(typeof(T));
}

调用GetShape

Circle c = GetShape<Circle>();
Rectangle r = GetShape<Rectangle>();

修改您可以使用new Constraint

进行无反射
  

在泛型类中将新约束应用于类型参数   创建该类型的新实例,如以下示例所示:

public T GetShape<T>() where T : Shape, new()
{
    return new T();
}

答案 3 :(得分:1)

您可以简单地将形状类嵌套在GetShape静态类中,而不是使用函数,并根据需要从该静态类创建新形状。

public static class GetShape {
    public class Circle() { .. }
    public class Square() { .. }
    public class Triangle() { .. }
    ...
}


var NewShape = new GetShape.Circle();

但是,如果您不希望这样做,我会建议使用泛型。

答案 4 :(得分:0)

如果你想做某事Circle - 具体你必须转换为这种特定类型。

您可以使用dynamic个对象,但在这种情况下,您会在编译阶段丢失类型安全检查。