Reputation: 148524
I have an object
.
This object is casting an Items Container
(I don't know what items, but I can check).
But is there any code which can help me find how many items it contains?
I mean
object[] arrObj = new object[2] {1, 2};
object o = (object)arrObj;
In this case arrObj
is an array so I can check:
((Array)o).Length
//2
But what if I have those 2 others ?
ArrayList al = new ArrayList(2);
al.Add(1);
al.Add(2);
object o = (object)al ;
and
List<object> lst= new List<object>(2);
object o = (object)lst;
Is there any general code which can help me find how many items are in this casted object (o
in this samples) ?
Of course I can check if (o is ...) { }
but Im looking for more general code.
Upvotes: 2
Views: 256
Reputation: 1500675
Well the most basic interface it could implement would be IEnumerable
. Unfortunately even Enumerable.Count
from LINQ is implemented for IEnumerable<T>
, but you could easily write your own:
public static int Count(IEnumerable sequence)
{
// Shortcut for any ICollection implementation
var collection = sequence as ICollection;
if (collection != null)
{
return collection.Count;
}
var iterator = sequence.GetEnumerator();
try
{
int count = 0;
while (iterator.MoveNext())
{
count++;
}
return count;
}
finally
{
IDisposable disposable = iterator as IDisposable;
if (disposable != null)
{
disposable.Dispose();
}
}
}
Note that this is basically equivalent to:
int count = 0;
foreach (object item in sequence)
{
count++;
}
... except that because it never uses Current
, it wouldn't need to do any boxing if your container was actually an int[]
for example.
Call it with:
var sequence = container as IEnumerable;
if (sequence != null)
{
int count = Count(sequence);
// Use the count
}
It's worth noting that avoiding boxing really is a bit of a micro-optimization: it's unlikely to really be significant. But you can do it once, just in this method, and then take advantage of it everywhere.
Upvotes: 2
Reputation: 174329
You can cast to the interface every container implements: IEnumerable
. However, to be more performant, it is a good idea to first try IEnumerable<T>
:
var count = -1;
var enumerable = lst as IEnumerable<object>;
if(enumerable != null)
count = enumerable.Count();
else
{
var nonGenericEnumerable = lst as IEnumerable;
count = nonGenericEnumerable.Cast<object>().Count();
}
For Count()
to be available, you need to add using System.Linq;
to your .cs file.
Please note that this code has one big advantage: If the collection implements ICollection<T>
- like List<T>
or strong typed arrays of reference types - this code executes in O(1) [Assuming the concrete implementation of ICollection<T>.Count
executes in O(1)]. Only if it doesn't - like ArrayList
or strong typed arrays of value types - does this code execute in O(n) and additionally, it will box the items in the case of an array of value types.
Upvotes: 4
Reputation: 190943
You could use linq.
var count = ((IEnumerable)o).Cast<object>().Count();
Ensure that the type o
has implements IEnumerable
and that you have using System.Linq
at the top of your file.
Upvotes: 3