是否可以在 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 ...) { }
但我正在寻找更通用的代码。
您可以将强制转换为每个容器实现的接口: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
}
值得注意的是,避免拳击确实是一种微观优化:它不太可能真正重要。但是你可以做一次,就用这种方法,然后在任何地方利用它。