4

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

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

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

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

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

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

唯一的问题是它甚至不会运行,因为它需要强制转换。

这实际上会起作用:

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

我对那个演员并不疯狂,我怎样才能避免它并且仍然完成一种让方法返回基类的方法,以便我可以返回任何兼容的子类。

4

5 回答 5

5

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

public T GetShape<T>() where T : Shape, new()
{
    return new T();
}
于 2014-05-30T10:05:06.570 回答
3

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

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

你的意思是这样的:

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

或者

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

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

var circle = shapecreator.GetCircle();

如果类型不是静态已知的,但只能在运行时确定,您将需要逻辑来决定调用什么方法,例如 using iforswitch语句。话虽这么说,你也需要这样的逻辑来进行演员表,所以这并不是一个真正的缺点。

另一种选择可能是使用抽象工厂设计模式,其中您有一个ShapeFactoryBase带有方法的类,以及从它继承并覆盖该方法virtual Shape Create()的派生类。不过,您仍然需要演员阵容,并且您仍然需要逻辑来决定要转换为哪种类型。CircleFactoryCreate()

于 2014-05-30T10:04:42.407 回答
1

您可以使用泛型方法通过方法调用传递您想要的类型。在该方法中,您可以使用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>();

编辑您可以使用新的约束不反射地做到这一点

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

public T GetShape<T>() where T : Shape, new()
{
    return new T();
}
于 2014-05-30T10:03:38.230 回答
1

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

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


var NewShape = new GetShape.Circle();

但是,如果您不想这样做,我建议您使用泛型漏洞利用。

于 2014-05-30T10:13:33.053 回答
0

如果你想做一些Circle特定的事情,你必须强制转换为这个特定的类型。

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

于 2014-05-30T10:02:06.123 回答