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

本文关键字:基类 派生 对象 任何 返回 何编写 函数 一个 | 更新日期: 2023-09-27 18:16:03

我有一个基类a

从这个基类中,我派生了一堆其他类,比如A1, A2, A3…

我有第三个类,比如说b。它的一个方法需要能够返回任何类,只要它是从a派生的。

我试了如下:

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

然而,这返回一个错误,说不能将类型A1转换为t

这个泛型返回可以实现吗?

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

如果你知道你的类将继承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();
    }
}

听起来你需要把它和工厂结合起来:

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

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

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

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