繁体   English   中英

如何声明一个返回“ anything”(C#)通用集合的方法

[英]How to declare a method that returns a generic collection of “anything” (C#)

我正在使用从抽象基类派生的通用集合类的层次结构来存储也从抽象基类派生的实体项目:

abstract class ItemBase { }

class MyItem : ItemBase
{
    public MyItem()
    {
    }
}


abstract class CollectionBase<T> : Collection<T> where T : ItemBase, new() { }

class MyCollection : CollectionBase<MyItem> { }

此模型的目标是对从CollectionBase <T>派生的任何类的成员强制执行严格的类型约束,并确保这些成员具有默认的公共构造函数。 到目前为止,它仍然有效。

现在,我想创建一个工厂方法,该方法返回一个从CollectionBase <T>派生的类的实例。 我了解通常的方法是:

public CollectionBase<T> CreateCollection<T>();

... 或者可能 ...

public T Create CreateCollection<T>();

但是,问题在于调用例程不知道需要什么“ T”。 工厂方法本身必须确定要返回的特定集合类型。 因此,我需要一个非泛型方法签名,该签名应显示“返回类型将从CollectionBase <T>派生”。 我设想这样的事情(如果合法的话)...

public CollectionBase<> CreateCollection();

我认为这是棘手的泛型方差问题中的另一个问题,但是即使阅读了Eric Lippert对此主题的详尽解释,我仍然不清楚我要做什么在C#4.0中是否可行,以及是否有一个简单的方法。 C#3.0中的解决方法。

预先感谢您的想法。

假设工厂方法正在创建一个项目。 你将会拥有:

public ItemBase CreateItem();

您必须使用ItemBase因为您无法了解更多具体信息。 将该原理应用于收集方法,您将获得:

public CollectionBase<ItemBase> CreateCollection();

由于缺乏差异,您需要一个适配器类,该适配器类从CollectionBase<ItemBase>派生并包装所创建的实际集合。

在C#4.0中,您只需返回实际的集合。

编辑:工厂可能看起来像这样,嵌入了适配器:

public class CollectionFactory
{
    public CollectionBase<ItemBase> CreateCollection()
    {
        if(someCondition)
        {
            return CreateAdapter(new MyCollection());
        }
        else
        {
            return CreateAdapter(new MyOtherCollection());
        }
    }

    private static CollectionAdapter<T> CreateAdapter<T>(CollectionBase<T> collection) where T : ItemBase, new()
    {
        return new CollectionAdapter<T>(collection);
    }

    private class CollectionAdapter<T> : CollectionBase<ItemBase> where T : ItemBase, new()
    {
        private CollectionBase<T> _collection;

        internal CollectionAdapter(CollectionBase<T> collection)
        {
            _collection = collection;
        }

        // Implement CollectionBase API by passing through to _collection
    }
}

您可能需要的是:

public CollectionBase<Object> CreateCollection();

因为每个类都直接或间接地继承自Object类。

我还没有真正做到这一点,并且道歉,如果这是完全幼稚,但...

public CollectionBase<Object> CreateCollection();

如果您真的希望它是任何东西,则可以返回ICollection,然后您的使用者可以根据需要调用.Cast<ItemBase>()扩展方法。

据我了解,在.NET 4.0中,您可以返回CollectionBase<ItemBase> ,但是我还没有在Beta上尝试过它。

暂无
暂无

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

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