C# GetEnumerator中的异常,并且在任何情况下都能够调用Count()。?@MatíasFidemraizer异常抛出只是一个占位符,以确保尽可能避免枚举。它可以被一个很长的方法调用,或者只是一个非常大的集合,或者在枚举时发生变化的集合(例如锁定对象

C# GetEnumerator中的异常,并且在任何情况下都能够调用Count()。?@MatíasFidemraizer异常抛出只是一个占位符,以确保尽可能避免枚举。它可以被一个很长的方法调用,或者只是一个非常大的集合,或者在枚举时发生变化的集合(例如锁定对象,c#,linq,C#,Linq,GetEnumerator中的异常,并且在任何情况下都能够调用Count()。?@MatíasFidemraizer异常抛出只是一个占位符,以确保尽可能避免枚举。它可以被一个很长的方法调用,或者只是一个非常大的集合,或者在枚举时发生变化的集合(例如锁定对象,这在异步环境中可能会有风险)。OrderBy也有同样的问题OrderBy不会更改计数,但调用count()仍会执行完整排序。您可以获得正确的计数,而无需使用一些反射单位进行排序。我认为,通过调用LINQ方法,您希望它能够枚举。这就像说,for



GetEnumerator
中的异常,并且在任何情况下都能够调用
Count()
。?@MatíasFidemraizer异常抛出只是一个占位符,以确保尽可能避免枚举。它可以被一个很长的方法调用,或者只是一个非常大的集合,或者在枚举时发生变化的集合(例如锁定对象,这在异步环境中可能会有风险)。
OrderBy
也有同样的问题
OrderBy
不会更改计数,但调用
count()
仍会执行完整排序。您可以获得正确的计数,而无需使用一些反射单位进行排序。我认为,通过调用LINQ方法,您希望它能够枚举。这就像说,
foreach
应该尽可能避免枚举。您希望LINQ保护用户不被低效使用。但添加魔法会使我们很难对其行为进行推理(和控制),尤其是当方法被链接时。我会说“如果你不能做到时间,就不要犯罪。”@Bentheii如果你实现
IEnumerable
,那么避免枚举又有什么意义呢?如果您不希望给定的对象是可枚举的,那么就不能实现整个接口。我弄错了吗OAnyway,在
GetEnumerator
中抛出异常,并且在任何情况下都能够调用
Count()
。?@Matíasfidemrazier异常抛出只是一个占位符,以确保尽可能避免枚举。它可以被一个很长的方法调用,或者只是一个非常大的集合,或者在枚举时发生变化的集合(例如锁定对象,这在异步环境中可能会有风险)。
OrderBy
也有同样的问题
OrderBy
不会更改计数,但调用
count()
仍会执行完整排序。您可以获得正确的计数,而无需使用一些反射单位进行排序。我认为,通过调用LINQ方法,您希望它能够枚举。这就像说,
foreach
应该尽可能避免枚举。您希望LINQ保护用户不被低效使用。但添加魔法会使我们很难对其行为进行推理(和控制),尤其是当方法被链接时。我会说“如果你不能做到时间,就不要犯罪。”@Bentheii如果你实现
IEnumerable
,那么避免枚举又有什么意义呢?如果您不希望给定的对象是可枚举的,那么就不能实现整个接口。我弄错了吗OI意识到这一点,我是说可以改进Select方法以返回ICollection类型的对象(如果源也是ICollection),从而优化Count()的用法method@bentheiii:没错。但可能不是为了保持懒惰的执行而实现的。@Bentheii:LINQ是关于懒惰的。Select不会返回内容集合。它返回一些东西,当您迭代时,它将通过链一次拉动一个项目。这意味着当您选择
时没有存储空间。将结果存储在集合中会对LINQ的预期用例造成灾难性的影响。把它想象成一个一次处理一个项目(以非常短视的方式)的管道,而不是生成(存储的)集合的操作。@spender那么为什么不返回一个包装输入集合的对象呢?它仍然是惰性枚举,需要最小的存储空间(我不认为比常规Select的枚举器大多少),但它还维护ICollection接口,以及附带的所有好处。@bentheii当下游用户想要使用
ICollection.Add
包装的集合时会发生什么?您是否需要提供反向投影方法?LINQ实际上并不涉及集合、计数和索引,但您有机会将物化集合与扩展方法(如
ToList
ToArray
ToDictionary
ToLookup
)混合使用。试图将所有这些都塞进核心LINQ会使它变得笨拙(想想需要进行的所有不同类型的特征检测),而且很可能是行不通的。我意识到这一点,我是说Select方法可以改进以返回ICollection类型的对象(如果源也是ICollection)优化计数的用法()method@bentheiii:没错。但可能不是为了保持懒惰的执行而实现的。@Bentheii:LINQ是关于懒惰的。Select不会返回内容集合。它返回一些东西,当您迭代时,它将通过链一次拉动一个项目。这意味着当您选择
时没有存储空间。将结果存储在集合中会对LINQ的预期用例造成灾难性的影响。把它想象成一个一次处理一个项目(以非常短视的方式)的管道,而不是生成(存储的)集合的操作。@spender那么为什么不返回一个包装输入集合的对象呢?它仍然是惰性枚举,需要最小的存储空间(我不认为比常规Select的枚举器大多少),但它还维护ICollection接口,以及附带的所有好处。@bentheii当下游用户想要使用
ICollection.Add
包装的集合时会发生什么?您是否需要提供反向投影方法?LINQ实际上并不涉及集合、计数和索引,但您有机会将物化集合与扩展方法(如
ToList
ToArray
ToDictionary
ToLookup
)混合使用。试图将所有这些都塞进核心LINQ将使其难以操作(想想需要进行的所有不同类型的特征检测),而且很可能是不可行的。
public class DummyCollection : ICollection<int>
{
        public IEnumerator<int> GetEnumerator()
        {
            throw new Exception();
        }
        public int Count
        {
            get
            {
                return 10;
            }
        }
    //some more interface methods
}
var d = new DummyCollection();
Console.WriteLine(d.Count());
var l = d.Select(a=> a);
Console.WriteLine(l.Count());
public static int Count<TSource>(this IEnumerable<TSource> source)
{
    if (source == null) throw Error.ArgumentNull("source");

    ICollection<TSource> collectionoft = source as ICollection<TSource>;

    if (collectionoft != null) return collectionoft.Count;

    ICollection collection = source as ICollection;

    if (collection != null) return collection.Count;

    int count = 0;
    using (IEnumerator<TSource> e = source.GetEnumerator()) {
        checked {
            while (e.MoveNext()) count++;
        }
    }
    return count;
}