是否可以在 c# 中从通用容器中计算一些东西

本文关键字:计算 是否 | 更新日期: 2023-09-27 17:56:55

我有一个object .

这个对象正在投射Items Container(我不知道是什么项目,但我可以检查)。

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

我的意思是

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

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

((Array)o).Length//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 ...) { }但我正在寻找更通用的代码。

是否可以在 c# 中从通用容器中计算一些东西

您可以将强制转换为每个容器实现的接口: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) 中执行,此外,它还会在值类型数组的情况下对项目进行装箱。

你可以

使用 linq。

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

确保类型o具有实现IEnumerable,并且using System.Linq位于文件顶部。

它可以实现的最基本的接口是IEnumerable。不幸的是,即使是 LINQ 的Enumerable.Count也是为 IEnumerable<T> 实现的,但您可以轻松地编写自己的:

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
}

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