如何编写一个函数来返回从C#中的基类派生的任何对象?

时间:2014-08-03 00:23:45

标签: c# generics

我有一个基类,比如A。

从那个基类我得到了一堆其他类,比如A1,A2,A3 ......

我有第三个类,比如说B.只要它来自A,它就需要能够返回任何类的方法之一。

我尝试了以下内容:

public T getObject<T>() where T : A
{
   return (new A1());
}

但是,这会返回一个错误,表示无法将A1类型转换为T.

这种通用回报能否实施?

4 个答案:

答案 0 :(得分:2)

如果你知道你的班级将继承A,但不需要知道确切的类型,那么你就不需要泛型:

public A getObject()
{
    return new A1();
}

如果您的示例已编译,则意味着您可以调用

A2 result = getObject<A2>();

但是getObject的实施始终会返回new A1()。由于A1没有继承A2,因此这是错误的。

听起来你可能希望根据某些神秘逻辑的结果返回不同的类型。这很好,仍然不需要泛型:

public A getObject()
{
    switch(MysteryLogic())
    {
        case MysteryLogicResult.One:
            return new A1();
        case MysteryLogicResult.Two:
            return new A2();
        case MysteryLogicResult.Three:
            return new A3();
    }
}

答案 1 :(得分:2)

听起来你需要将它与工厂结合起来:

public interface IAFactory
{
    A Build();
}

然后你可以改变你的通用方法:

public A getObject<T>() where T : new, IAFactory
{
    return getObject(new T()
}

public A getObject<T>(T factory) where T : IAFactory
{
    return factory.Build();
} 

您需要更改A1,A2的实现:

public class A1 : A, IAFactory
{
   public A1 Build(){
      //Logic for constructing A1
   }
}

或者创建专门的课程:

public class A1Factory : IAFactory
{
   public A1 Build(){
      //Logic for constructing A1
   }
}

然后你可以打电话给你的方法:

public class Test
{
  public void CallBMethod()
  {
     //option 1
     A option1 = new B().getObject<A1>();

     //option 2
     A option2 = new B().getObject<A1Factory>();

    //Or skip the B.getObject method and access factory directly:
    A a1 = new A1Factory().Build();
    A a2 = new A2Factory().Build();
  }
}

答案 2 :(得分:1)

TL; DR:您必须返回T,因为这是您为方法声明的返回类型。

如果你返回A1,它看起来应该像你说的那样工作。但是你忘记了你也可以通过传入A2来调用方法,在这种情况下返回A1是无效的:

var myObject = getObject<A1>(); // this would have worked
var myObject = getObject<A2>(); // this can not work

这将失败,因为A1不能分配给A2类型。因为第二种情况不起作用,编译器不允许你这样做。

那么正确的方法是返回新的T:

public T getObject<T>() where T : A
{
   return (new T());
}

var myObject = getObject<A1>(); // works
var myObject = getObject<A2>(); // also works

答案 3 :(得分:1)

您可以使用工厂模式获得所需的结果:

public A GetObject (string type) {
     A aObj ;
     if (type == "A1") {
        aobj = new A1 () ;
     else if (type == "A2") {
         aobj = new A2 () ;
     }
     return aObj ;
}