13

In a method, I get an object.

In some situation, this object can be an IList of "something" (I have no control over this "something").

I am trying to:

  1. Identify that this object is an IList (of something)
  2. Cast the object into an "IList<something>" to be able to get the Count from it.

For now, I am stuck and looking for ideas.

remio
  • 1,242
  • 2
  • 15
  • 36
  • Is the `Count` *all* you want? If so, you don't need it to be an `IList`, a simple `IEnumerable` will do. – AakashM Jan 25 '12 at 09:33
  • Yes, `Count` is all that I want. However, I can't see any `Count` in `IEnumerable`? – remio Jan 25 '12 at 09:43

4 Answers4

23

You can check if your object implements IList using is.

Then you can cast your object to IList to get the count.

object myObject = new List<string>();

// check if myObject implements IList
if (myObject  is IList)
{
   int listCount = ((IList)myObject).Count;
}
dknaack
  • 60,192
  • 27
  • 155
  • 202
  • Ah, great, this is what I missed. I was looking for `IList` being an `IList`. But as `List` and `Collection` are `IList`s, This is enough for me. Thanks. – remio Jan 25 '12 at 09:48
4
if (obj is ICollection)
{
    var count = ((ICollection)obj).Count;
}
Danny Varod
  • 17,324
  • 5
  • 69
  • 111
  • Thanks for your answer. Is there a benefit of casting into `ICollection` over casting into `IList`? – remio Jan 25 '12 at 09:52
  • 1
    Will work with more types of collections, casting to IEnumerable and reading .Count() instead of .Count will work with even more. – Danny Varod Jan 25 '12 at 10:00
  • 1
    @DannyVarod but `IEnumerable.Count()` risks enumerating the collection in order to count its items. – phoog Jan 25 '12 at 15:10
  • 1
    Depends on actual type of collection. For lists it won't. – Danny Varod Jan 25 '12 at 17:33
  • @phoog, This is exactly what I was suspicious about, but as it won't be the case for lists according to DannyVarod' statemtent, it seems to be a good compromise to be able to handle ost of the situations. Developers "just" need to be aware of it. – remio Jan 26 '12 at 07:10
  • @remio Actually, I was just looking at ILSpy, and the `IEnumerable` approach won't work for your use case. The `Count()` extension method is for `IEnumerable`, not `IEnumerable`, so you're still left with the problem of determining the type of the collection's members before you can call `Count()`. – phoog Jan 26 '12 at 21:51
  • @remio Additionally, if you call `Cast` as suggested by AakashM, you're no longer counting the members of the list directly; you're getting them from the cast iterator, which doesn't give access to the `Count` property of the wrapped object. – phoog Jan 26 '12 at 21:57
  • You can determine generic type parameter then use that for a more specific cast, however, that would be an overkill for this simple situation. That is why I suggested ICollection at first. – Danny Varod Jan 26 '12 at 22:55
1
        object o = new int[] { 1, 2, 3 };

        //...

        if (o is IList)
        {
            IList l = o as IList;
            Console.WriteLine(l.Count);
        }

This prints 3, because int[] is a IList.

Petar Ivanov
  • 91,536
  • 11
  • 82
  • 95
0

Since all you want is the count, you can use the fact that anything that implements IList<T> also implements IEnumerable; and furthermore there is an extension method in System.Linq.Enumerable that returns the count of any (generic) sequence:

var ienumerable = inputObject as IEnumerable;
if (ienumerable != null)
{
    var count = ienumerable.Cast<object>().Count();
}

The call to Cast is because out of the box there isn't a Count on non-generic IEnumerable.

Community
  • 1
  • 1
AakashM
  • 62,551
  • 17
  • 151
  • 186
  • Ah, yes, I get it! But would I have to expect performance impacts with this implementation? – remio Jan 25 '12 at 10:51
  • @remio yes, you would. Because you're calling `Cast`, you will not be able to benefit from the underlying list's `Count` property, so you will indeed iterate the entire list in order to count the items. Furthermore, if the list's elements are of a value type, you'll have to box each of them because of the cast to `object`. – phoog Jan 26 '12 at 21:53