简体   繁体   English

可以从基抽象类上的静态方法返回派生的泛型类型吗?

[英]Can a derived generic type be returned from a static method on the base abstract class?

Abstract class: 抽象类:

abstract class PersistentList<T>

public static PersistentList<T> GetInstanceOfDerivedClass()
{
    //???
}

Derived class: 派生类:

public class Managers : PersistentList<Manager> 

So, I'd like to: 因此,我想:

Managers managers = Managers.GetInstanceOfDerivedClass();

Is that possible? 那可能吗?

Choices are: 选择是:

int clientID = 3;

Managers managers = Managers.For("Client", new { ClientID = clientID});

Managers managers = new Managers(new { ClientID = clientID });

Managers managers = new Managers();
managers.ClientID = clientID;
managers.Load("ForClient");
//alternatively:
Database.Load(managers, "ForClient");

//this works, however requires the above code in the constructor.
Managers managers = new Managers(clientID);

//If the static method on the abstract class (Managers.For) could determine
//the type calling, it would eliminate the need for repetitive constructors.

All the above are available, just trying to decide on a good technique. 以上都是可用的,只是试图决定一种好的技术。

You can't do it with a static method. 您不能使用静态方法来执行此操作。 I'm not sure why you would want to, but you can do this 我不确定为什么要这么做,但是您可以这样做

    public abstract class PersistentList<T>
    {
        public PersistentList<T> GetInstanceOfDerivedClass()
        {
            return (PersistentList<T>)Activator.CreateInstance(this.GetType());
        }
    }

Usage 用法

Managers managers = (Managers)new Managers().GetInstanceOfDerivedClass();

I think this is about the simplest it'll be if you need strong typing (ie that the method will return Managers , not just PersistentList<Manager> when requesting a Managers ): 我认为这是最简单的,如果您需要强类型化(即,该方法将在请求Managers时返回Managers ,而不仅仅是PersistentList<Manager> ):

static class PersistentList
{
    public static T GetInstanceOfDerivedClass<T, U>() where T : PersistentList<U>
    {
        throw new NotImplementedException();
    }
}

Managers managers = PersistentList.GetInstanceOfDerivedClass<Managers, Manager>();

You might also do: 您可能还会这样做:

abstract class PersistentList<T, U> where T : PersistentList<T, U>
{
    public static T GetInstanceOfDerivedClass()
    {
        throw new NotImplementedException();
    }
}
public class Managers : PersistentList<Managers, Manager>
{
}

This lets you use the signature in your example, Managers.GetInstanceOfDerivedClass() . 这使您可以在示例中使用签名Managers.GetInstanceOfDerivedClass() I find this design pattern confusing, however, and would discourage its use. 但是,我发现这种设计模式令人困惑,并且会阻止其使用。

This seems like an odd situation to be in but assuming you are somehow confined to such a pattern, this is the closest thing I could come up with (still not exactly what you are trying to do): 这似乎是一种奇怪的情况,但是假设您被某种方式限制在这种模式下,这是我能想到的最接近的方法(仍然不完全是您要尝试做的事情):

abstract class PersistentList<T>
{
    public static T2 GetInstanceOfDerivedClass<T2>() where T2 : PersistentList<T>
    {
        return (T2)Activator.CreateInstance(typeof(T2));
    }
}

class Manager { }

class Managers : PersistentList<Manager> { }

Usage: 用法:

Managers managers = PersistentList<Manager>.GetInstanceOfDerivedClass<Managers>();

One could use a pattern like you describe, but in some cases it may be useful to have the factory method be a generic method within a non-generic static class, especially if the method will take any parameters which could be used for type inference. 可以使用您所描述的模式,但是在某些情况下,将工厂方法作为非泛型静态类中的泛型方法可能会很有用,尤其是如果该方法将采用任何可用于类型推断的参数时。 For example, if one had a method to create a new collection which would be initially populated from a T[] , it may in some cases be more convenient to use SuperCollection<T> SuperCollection.Create<T>(T InitialValues[]) than SuperCollection<T> SuperCollection<T>.Create(T InitialValues[]) , since the former could automatically infer the type of collection to create based upon the type of the array parameter. 例如,如果有一种方法可以创建一个新集合,该方法最初是从T[]填充的,那么在某些情况下,使用SuperCollection<T> SuperCollection.Create<T>(T InitialValues[])可能会更方便。而不是SuperCollection<T> SuperCollection<T>.Create(T InitialValues[]) ,因为前者可以根据数组参数的类型自动推断要创建的集合的类型。

Other than that, I think what you describe is a perfectly reasonable pattern in cases where the type of object which is created may depend upon various factors which might not be known at compile time. 除此之外,在所创建的对象类型可能取决于编译时可能未知的各种因素的情况下,我认为您所描述的是一种完全合理的模式。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM