是否有可能从c#中的一般容器中计算一些东西?

时间:2013-02-01 14:06:42

标签: c# .net .net-4.0

我有object

此对象正在投射Items Container(我不知道哪些项目,但我可以查看)。

但有没有任何代码可以帮助我找到它包含多少项目?

我的意思是

 object[] arrObj = new object[2] {1, 2};
 object o = (object)arrObj;

在这种情况下,arrObj是一个数组,所以我可以检查:

((Array)o).Length // 2

但是如果我有其他2个怎么办?

 ArrayList al = new ArrayList(2);
           al.Add(1);
           al.Add(2);
 object o = (object)al ;

 List<object> lst= new List<object>(2);
 object o = (object)lst;

是否有任何通用代码可以帮助我找到此演示对象中有多少项(此示例中为o)?

当然我可以查看if (o is ...) { },但我正在寻找更通用的代码。

3 个答案:

答案 0 :(得分:4)

您可以将每个容器实现转换为接口:IEnumerable。但是,为了提高性能,首先尝试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();
}

要使Count()可用,您需要将using System.Linq;添加到.cs文件中。

请注意,此代码有一个很大的优势:如果集合实现ICollection<T> - 如List<T>或强类型的引用类型数组 - 此代码在O(1)中执行[假设ICollection<T>.Count的具体实现在O(1)] 中执行。只有当它没有 - 比如ArrayList或强类型的值类型数组 - 这个代码才会在O(n)中执行,此外,它会在值类型数组的情况下对项进行打包。

答案 1 :(得分:3)

你可以使用linq。

var count = ((IEnumerable)o).Cast<object>().Count();

确保o类型具有实施IEnumerable,并且您的文件顶部有using System.Linq

答案 2 :(得分:2)

它可以实现的最基本的界面是IEnumerable。不幸的是,甚至来自LINQ的Enumerable.Count都是为IEnumerable<T>实现的,但您可以轻松编写自己的:{/ p>

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

请注意,这基本上等同于:

int count = 0;
foreach (object item in sequence)
{
    count++;
}

...除了因为它从不使用Current之外,如果您的容器实际上 int[],则不需要进行任何装箱。

用以下方式调用:

var sequence = container as IEnumerable;
if (sequence != null) 
{
    int count = Count(sequence);
    // Use the count
}

值得注意的是,避免拳击确实是一种微观优化:它不太可能真正重要。但你可以一次,只需用这种方法,然后在任何地方利用它。