有没有一种好的方法可以清空一个ICollection<T>,而不需要知道T是什么?

4
我有一个包含不同项目类型的集合列表。 该列表的类型为List<IEnumerable>,因为IEnumerable是来自ICollection<T>的唯一非泛型接口,并且我需要在此列表中添加例如ICollection<Contact>ICollection<Partnership>集合。
稍后,在实体实用程序代码中,我需要清除这些集合。到目前为止,我找到的唯一解决方案是:
collection.GetType().GetInterface("ICollection`1").InvokeMember("Clear",
        BindingFlags.Public | BindingFlags.Instance | BindingFlags.InvokeMethod,
        null,
        collection,
        new object[0]);

有没有更优雅的方案可供使用?


大多数具体的集合类型实现了非泛型的 ICollection - SLaks
2
ICollection<T> 有 Clear() 方法,而 ICollection 没有 Clear() 方法。 - Matthew Watson
2
你们误解了。Clear 只有在集合是只读的情况下才会抛出 NotSupportedException 异常! - Kirk Woll
3
@KirkWoll:我在这里没有看到jnm2正在使用只读集合的任何迹象。(事实上,询问如何清除只读集合会相当矛盾) - Chris Sinclair
2
@AdamHouldsworth:我不知道那个。改成IList吧。 - SLaks
显示剩余3条评论
3个回答

10

如果你的最底层类型被ICollection<T>限制,那么选择就不多了。一种较少冗长的实现方式是涉及DLR,使用dynamic并进行鸭子类型:

    static void Main(string[] args)
    {
        var listOfLists = new List<IEnumerable>();

        var names = new List<string>();
        var ages = new List<int>();

        listOfLists.Add(names);
        listOfLists.Add(ages);

        foreach (dynamic list in listOfLists)
        {
            list.Clear();
        }
    }

或者你可以假设已经实现的接口,并测试其中一个是否定义了Clear

        foreach (var list in listOfLists)
        {
            if (list is IList)
            {
                (list as IList).Clear();
            }
        }

如果您可以进入类型层次结构,请创建您自己的接口,供您的集合使用,并定义您自己的Clear

这主要是因为.NET 2.0之前的集合和接口与.NET 2.0的集合和接口不兼容造成的问题。


“dynamic”表单更加简洁,我喜欢它。 - jnm2
@jnm2请注意,任何失败的绑定都会在运行时发生并创建运行时错误。 - Adam Houldsworth

0

你可以为业务类使用通用接口,比如 IObject (或者甚至是 object 类)。尝试一下这个:

class Program
{
    static void Main(string[] args)
    {
        var list = new MyList();

        var contacts = new ContactCollection();
        var partnerships = new PartnershipCollection();

        contacts.Add(new Contact());
        partnerships.Add(new Partnership());

        list.Add(contacts);
        list.Add(partnerships);

        list.ClearCollections();
    }

    class MyList : List<ICollection<IObject>>
    {
        public void ClearCollections()
        {
            this.ForEach((a) => a.Clear());
        }
    }

    interface IObject { }
    class Contact : IObject { }
    class Partnership : IObject { }
    class ContactCollection : ICollection<IObject> { }
    class PartnershipCollection : ICollection<IObject> { }
}

-2
为什么需要使用反射?因为ICollection接口包含Clear方法,那么无论实现它的具体类型是什么,都会有此方法。
所以简单地说
ICollection collection = new List<Something>();
collection.Clear();

好的,我会做。


他的问题是他有一个包含ICollection<T>List<IEnumerable>。这看起来似乎行不通,除非他需要完全清空“集合列表”。从他的描述听来,他实际上想要能够从这个列表中选择一个集合并只清除一个集合。 - Earlz
1
ICollection 是只读的,而 Clear 抛出 NotSupportedException。http://msdn.microsoft.com/zh-cn/library/5axy4fbh(v=vs.85).aspx - andreister
这是特定于ICollection<T>的,因为非泛型的ICollection没有Clear - Adam Houldsworth
嗯,我明白你的意思,他还没有澄清任何事情,这不太方便。在这种情况下,我会更新另一个答案。 - Stokedout

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接