C# dot net是否具有类似IEnumerable的接口,并具有Count属性?

C# dot net是否具有类似IEnumerable的接口,并具有Count属性?,c#,.net,C#,.net,dot net是否具有类似IEnumerable的接口,并具有count属性?我知道诸如IList和ICollection这样的接口确实提供了Count属性,但这些接口似乎是为可变数据结构设计的,用作只读接口似乎是事后才想到的——当此属性为真时,存在IsReadOnly字段和引发异常的变体就是充分的证据为了这个 目前,我正在使用一个名为IReadOnlyCollection的自定义接口(请参阅我自己对这篇文章的回答),但我很高兴知道其他替代方法。IList可以将IsReadOnly返回为true

dot net是否具有类似IEnumerable的接口,并具有count属性?我知道诸如IList和ICollection这样的接口确实提供了Count属性,但这些接口似乎是为可变数据结构设计的,用作只读接口似乎是事后才想到的——当此属性为真时,存在IsReadOnly字段和引发异常的变体就是充分的证据为了这个


目前,我正在使用一个名为IReadOnlyCollection的自定义接口(请参阅我自己对这篇文章的回答),但我很高兴知道其他替代方法。

IList可以将IsReadOnly返回为true,这将集合标记为只读。除此之外,我恐怕不知道任何合适的方法。

如果您添加对System.Linq的引用(无论如何,在3.5中),您可以使用扩展方法使用IEnumerable进行计数。

因为它是一个接口,您必须自己实现Count属性,为什么不创建一个继承IEnumerator并添加Count属性的新接口?

ICollection族和IEnumerable族之间的关键区别在于,现有项目的数量不确定(通常项目会根据需要生成/加载/水合)-在某些情况下,可枚举项可能永远无法完成生成结果,这就是缺少计数的原因

根据您的需求,可以导出和添加计数,但这与此精神背道而驰,这正是ICollection的目的——收集所有的东西

另一种方法可能是使用System.Linq.Enumerable.Count方法,即

using System.Linq;

class X
{
   void Y(IEnumerable<int> collection)
   {
      int itemCount = collection.Count();
   }
}
使用System.Linq;
X类
{
void Y(IEnumerable集合)
{
int itemCount=collection.Count();
}
}
或者使用(System.Linq.Enumerable).ToList()将枚举器中的所有项拉入一个集合,并从那里开始工作


(也是为了在有50个rep之前回答您的评论:“.Count()”位是对扩展类System.Linq.Enumerable上的扩展方法的调用-扩展方法可用于从IEnumerable派生的所有内容,因为代码具有“using System.Linq”这将该名称空间中所有类中的扩展方法纳入范围-在本例中是在类Enumerable中。如果您在VS中,按F12将进入S.L.Enumerable的定义。顺便说一句,C#深入是一本正确学习LINQ的好书-这是一个页面转换器,它确实可以帮助您了解与L相比的整个情况如果您想使用标准接口,就可以一块一块地获取LINQ的位)

IList
ICollection

请注意,如果不希望在类的公共接口中使用接口所需的方法,则可以“隐藏”这些方法——例如,因为向只读集合添加内容没有意义,所以可以执行以下操作:

void ICollection<DataType>.Add(DataType item)
{
    throw new NotSupportedException();
}

public DataType this[int index]
{
    get { return InnerList[index]; }
}

DataType IList<DataType>.this[int index]
{
    get { return this[index]; }
    set { throw new NotSupportedException(); }
}
void ICollection.Add(数据类型项)
{
抛出新的NotSupportedException();
}
公共数据类型此[int index]
{
获取{return InnerList[index];}
}
数据类型IList.this[int index]
{
获取{返回此[索引];}
设置{抛出新的NotSupportedException();}
}

等等。

考虑到一些评论,我决定使用一个实现自定义接口的包装器类

interface IReadOnlyCollection<T> : IEnumerable<T>
{
    int Count { get; }
}

//This can now be not misused by downcasting to List
//The wrapper can also be used with lists since IList inherits from ICollection
public class CollectionWrapper<T> : IReadOnlyCollection<T>
{

    public CollectionWrapper(ICollection<T> collection)
    {
        _collection = collection;
    }

    public int Count
    {
        get
        {
            return _collection.Count;
        }
    }

    public IEnumerator<T> GetEnumerator()
    {
        return (IEnumerator<T>)_collection.GetEnumerator();
    }

    IEnumerator IEnumerable.GetEnumerator()
    {
        return (IEnumerator)((IEnumerable)_collection).GetEnumerator();
    }

    ////////Private data///////
    ICollection<T> _collection;
}


class Program
{
    static void Main(string[] args)
    {
        List<int> list = new List<int>();

        list.Add(1);
        list.Add(2);
        list.Add(3);
        list.Add(4);

        CollectionWrapper<int> collection = new CollectionWrapper<int>(list);

        Console.WriteLine("Count:{0}", collection.Count);
        foreach (var x in collection)
        {
            Console.WriteLine(x);
        }

        foreach (var x in (IEnumerable)collection)
        {
            Console.WriteLine(x);
        }
    }
}
接口IReadOnlyCollection:IEnumerable
{
整数计数{get;}
}
//这一点现在不会被向下投射到列表中所滥用
//包装器也可以用于列表,因为IList继承自ICollection
公共类CollectionWrapper:IReadOnlyCollection
{
公共集合包装器(ICollection集合)
{
_收集=收集;
}
公共整数计数
{
得到
{
返回_collection.Count;
}
}
公共IEnumerator GetEnumerator()
{
return(IEnumerator)u collection.GetEnumerator();
}
IEnumerator IEnumerable.GetEnumerator()
{
return(IEnumerator)((IEnumerable)u collection.GetEnumerator();
}
////////私有数据///////
i收集(i)收集;;
}
班级计划
{
静态void Main(字符串[]参数)
{
列表=新列表();
增加第(1)款;
增加(2);
增加(3);
增加(4);
CollectionWrapper集合=新的CollectionWrapper(列表);
WriteLine(“Count:{0}”,collection.Count);
foreach(集合中的变量x)
{
控制台写入线(x);
}
foreach(在(IEnumerable)集合中的变量x)
{
控制台写入线(x);
}
}
}
谢谢大家的建议


编辑:现在不能被向下转换为列表(或其他任何内容)而滥用。

可以将数组转换为IList,这使得IList ReadOnly==true:)

听起来你真的只是想要-将其公开为
IList
,但是,通过这样包装原始列表,您只需获得一个具有适当计数的只读包装器。

正如Jon Skeet提到的,您最好使用System.Collections.ObjectModel.ReadOnlyCollection,而不是创建自己的包装器类

然后,您可以按如下方式实现示例:

class Program {
    static void Main(string[] args) {
        List<int> list = new List<int>();
        list.Add(1);
        list.Add(2);
        list.Add(3);
        list.Add(4);

        ReadOnlyCollection<int> collection = new ReadOnlyCollection<int>(list);
        Console.WriteLine("Count:{0}", collection.Count);
        foreach (var x in collection) {
            Console.WriteLine(x);
        }
        foreach (var x in (IEnumerable)collection) {
            Console.WriteLine(x);
        }
    }
}
类程序{
静态void Main(字符串[]参数){
列表=新列表();
增加第(1)款;
增加(2);
增加(3);
增加(4);
ReadOnlyCollection集合=新的ReadOnlyCollection(列表);
WriteLine(“Count:{0}”,collection.Count);
foreach(集合中的变量x){
控制台写入线(x);
}
foreach(在(IEnumerable)集合中的变量x){
控制台写入线(x);
}
}
}

从.Net 4.5开始,有两个新的接口:和

IReadOnlyCollection
是添加了
Count
属性的
IEnumerable
IReadOnlyList
还添加了