jnm2
jnm2

Reputation: 8354

Is there a good way to clear an ICollection<T> without knowing T?

I have a list of collections of various item types. The list is typed as List<IEnumerable>; because IEnumerable is the only non-generic interface from ICollection<T>, and I need to add e.g. ICollection<Contact> and ICollection<Partnership> collections in this list.

Later, in entity utility code, I need to clear the collections. The only solution I've found so far is:

collection.GetType().GetInterface("ICollection`1").InvokeMember("Clear",
        BindingFlags.Public | BindingFlags.Instance | BindingFlags.InvokeMethod,
        null,
        collection,
        new object[0]);

Is there anything more elegant I can use?

Upvotes: 5

Views: 4395

Answers (3)

Alex Filipovici
Alex Filipovici

Reputation: 32541

You might use a common interface for your business classes, like IObject (or maybe even the object class). Try this:

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> { }
}

Upvotes: 0

Adam Houldsworth
Adam Houldsworth

Reputation: 64467

There aren't many options if you're constrained by ICollection<T> as your lowest type. A less-wordy implementation that involves the DLR is to use dynamic and duck-type it:

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

Or you can make assumptions about possibly implemented interfaces and test for one with Clear defined:

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

If you can get into the type hierachy, create your own interface that your collections use and define your own Clear.

This is mainly a problem because the pre-.NET 2.0 collections and interfaces do not mesh well with the .NET 2.0 collections and interfaces.

Upvotes: 10

Stokedout
Stokedout

Reputation: 11045

Why do you need to use Reflection? as the ICollection interface includes the Clear method then whatever concrete type that implements this will have it covered.

So simply

ICollection collection = new List<Something>();
collection.Clear();

will do

Upvotes: -2

Related Questions