Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/286.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/.net/23.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 正在计算IEnumerable的计数(非泛型)_C#_.net_Linq_Extension Methods_Ienumerable - Fatal编程技术网

C# 正在计算IEnumerable的计数(非泛型)

C# 正在计算IEnumerable的计数(非泛型),c#,.net,linq,extension-methods,ienumerable,C#,.net,Linq,Extension Methods,Ienumerable,有人能帮我介绍一下IEnumerable(非通用接口)的Count扩展方法吗 我知道LINQ不支持它,但如何手动编写它?最简单的形式是: public static int Count(this IEnumerable source) { int c = 0; using (var e = source.GetEnumerator()) { while (e.MoveNext()) c++; } return c;

有人能帮我介绍一下
IEnumerable
(非通用接口)的
Count
扩展方法吗


我知道LINQ不支持它,但如何手动编写它?

最简单的形式是:

public static int Count(this IEnumerable source)
{
    int c = 0;
    using (var e = source.GetEnumerator())
    {
        while (e.MoveNext())
            c++;
    }
    return c;
}
然后,您可以通过查询
ICollection
来改进这一点:

public static int Count(this IEnumerable source)
{
    var col = source as ICollection;
    if (col != null)
        return col.Count;

    int c = 0;
    using (var e = source.GetEnumerator())
    {
        while (e.MoveNext())
            c++;
    }
    return c;
}
更新

正如Gerard在评论中指出的,非泛型
IEnumerable
不会继承
IDisposable
,因此正常的
using
语句将无法工作。如果可能,尝试处理此类枚举数可能仍然很重要-迭代器方法实现
IEnumerable
,因此可能会间接传递给此
Count
方法。在内部,该迭代器方法将取决于对
Dispose
的调用,以触发它自己的
try
/
最终使用
语句

为了在其他情况下简化此操作,您可以使用编译时不太繁琐的
语句来创建自己的
版本:

public static void DynamicUsing(object resource, Action action)
{
    try
    {
        action();
    }
    finally
    {
        IDisposable d = resource as IDisposable;
        if (d != null)
            d.Dispose();
    }
}
更新后的
Count
方法将是:

public static int Count(this IEnumerable source) 
{
    var col = source as ICollection; 
    if (col != null)
        return col.Count; 

    int c = 0;
    var e = source.GetEnumerator();
    DynamicUsing(e, () =>
    {
        while (e.MoveNext())
            c++;
    });

    return c;
}

不同类型的IEnumerable有不同的确定计数的优化方法;不幸的是,对于任何给定的IEnumerable,没有通用的方法可以知道哪种方法最适合,甚至没有任何标准的方法可以让IEnumerable指出以下哪种技术是最好的:

  • 直接询问对象即可。支持IEnumerable的某些类型的对象(如数组、列表和集合)的属性可以直接报告其中的元素数。
  • 枚举所有项目,丢弃它们,并计算枚举的项目数。
  • 将所有项目枚举到列表中,然后在需要再次使用枚举时使用该列表。
    在不同的情况下,上述每一项都将是最佳的。

    我认为,首先,用于表示元素序列的类型应该是ICollection,而不是IEnumerable


    ICollection
    ICollection
    都提供了一个Count属性,加上-每个ICollection也实现了IEnumerable。

    “查询IList”-或查询其基本接口ICollection我尝试了这个扩展,
    使用
    System.Collections.IEnumerable
    提供了一个编译错误。我将代码更改为编译的
    Count(此IEnumerable源代码)
    。@Daniel检查
    ICollection
    的答案更好,因为它值得…@Marc第一个
    .Cast().Count()
    已经进行了检查(通用和非通用)。但是是的,第二个解决方案可以通过检查来改进。将其转换为通用IEnumerable版本有什么意义?这将消除使用非泛型IEnumerable背后的原因——正是在您不知道/不关心元素类型的情况下。因此,您将无法对元素类型执行任何编译时强制转换,因为它们未知(如果已知-使用的IEnumerable首先应该是泛型的)。如果最终需要的是获取元素总数的方法,那么对象类型可能不应该是IEnumerable,而应该是ICollection。通用和非通用版本都提供了计数属性。我同意编辑答案中的“过早优化”论点。
    yourEnumerable.Cast<object>().Count()
    
    static class EnumerableExtensions
    {
        public static int Count(this IEnumerable source)
        {
            int res = 0;
    
            foreach (var item in source)
                res++;
    
            return res;
        }
    }