c#如何避免类型转换到子类
本文关键字:子类 类型转换 何避免 | 更新日期: 2023-09-27 18:06:06
假设我有一个基类Shape。然后是一些子类,比如circle和square。
让我们在另一个类中创建一个名为GetShape的方法:
public Shape GetShape()
{
return new Circle();
}
好的,这个想法是,我可以传入一个shapeType然后得到一个强类型Shape子类返回。上面的例子是对实际代码的大量简化,但我认为它已经表达了重点。
那么当我调用这个方法的时候它看起来会是
var shapeCreator = new ShapeCreator();
Circle myCircle = shapeCreator.GetShape();
唯一的问题是它甚至不会运行,因为它需要强制转换。
这将实际工作:
Circle myCircle = (Circle) shapeCreator.GetShape();
我对这种强制转换不感兴趣,我如何避免它,并且仍然可以实现一种方法返回基类,以便我可以返回任何兼容的子类。
您可以为此使用泛型,即使没有反射。这个示例在T
上使用无参数构造器过滤器(从Adil更改的示例):
public T GetShape<T>() where T : Shape, new()
{
return new T();
}
没有办法解决您的问题。但是,你说
我的想法是,我可以传入一个shapeType然后得到一个强类型type Shape子类返回
你的意思是:
var shape = shapecreator.GetShape(typeof(Circle));
或
var shape = shapecreator.GetShape<Circle>();
如果是,并且类型在编译时是静态已知的,只需执行
var circle = shapecreator.GetCircle();
如果类型不是静态已知的,但只能在运行时确定,您将需要逻辑来决定调用什么方法,例如使用if
或switch
语句。话虽如此,对于强制转换,您也需要这样的逻辑,所以这并不是一个真正的缺点。
另一个选择可能是使用抽象工厂设计模式,其中您有一个ShapeFactoryBase
类和一个virtual Shape Create()
方法,以及从它继承的派生类CircleFactory
,并覆盖Create()
方法。但是您仍然需要强制转换,并且您仍然需要逻辑来决定要强制转换为什么类型。
您可以使用泛型方法通过方法调用传递您想要的类型。在这个方法中,你可以使用Activator。创建对象的类型
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();
}
不使用函数,您可以简单地将形状类嵌套在GetShape
静态类中,并根据需要从该静态类创建新形状。
public static class GetShape {
public class Circle() { .. }
public class Square() { .. }
public class Triangle() { .. }
...
}
var NewShape = new GetShape.Circle();
但是,如果您不希望这样做,我建议使用泛型。
如果你想做一些特定于Circle
的事情,你必须转换为这种特定的类型。
您可以使用动态对象,但在这种情况下,您将失去编译阶段的类型安全检查。