如何在 IEnumerable 上实现 ICollection

本文关键字:实现 ICollection IEnumerable | 更新日期: 2023-09-27 18:37:28

我想知道如何对 MSDN 集合指南中Microsoft建议的内容进行编程,该指南指出以下内容:

AVOID using ICollection<T> or ICollection as a parameter just to access the
Count property. Instead, consider using IEnumerable<T> or IEnumerable and
dynamically checking whether the object implements ICollection<T> or ICollection.

简而言之,如何在 IEnumerable 上实现 ICollection? Microsoft在那篇文章中到处都有链接,但没有"这是你如何做到这一点"的链接。

这是我的场景。我有一个带有网格的 MVC Web 应用程序,该网格将对某些集合进行分页并具有排序功能。 例如,在"员工管理"屏幕上,我在网格中显示员工列表。

最初,我将集合返回为 IEnumerable。 当我不需要分页时,这很方便。 但是现在我面临着分页的问题,需要提取员工记录的计数来做到这一点。 一种解决方法是通过 ref 将 employeeCount 整数传递给我的 getEmployeeRecords() 方法并在该方法中分配值,但这很混乱。

根据我在StackOverflow上看到的内容,一般建议使用IEnumerable而不是ICollection,Collection,IList或List。 所以我不想就这个话题展开对话。我想知道的只是如何使 IEnumerable 实现 ICollection,并提取记录计数,所以我的代码更符合 Microsoft 的建议。演示这一点的代码示例或清晰的文章将有所帮助。

感谢您的帮助!

如何在 IEnumerable<T> 上实现 ICollection<T>

需要注意的一点是,如果使用 LINQ 的 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;
}

最初,我将集合返回为 IEnumerable。

好吧,你的问题有一半。返回类型应尽可能显式。如果您有集合,请将返回类型设置为该集合。(我忘记了在哪里,但这在指南中提到过。

根据我在StackOverflow上看到的内容,一般建议使用IEnumerable而不是ICollection,Collection,IList或List。

一些开发人员痴迷于将所有内容转换为 IEnumerable。我不知道为什么,因为Microsoft任何地方都没有指导说这是一个好主意。(我知道有些人认为它以某种方式使返回值不可变,但实际上任何人都可以将其转换回基类型并对其进行更改。或者只是使用dynamic,甚至没有注意到你给了他们一个 IEnumerable。

这是返回类型和局部变量的规则。对于参数,您应该尽可能接受。在实践中,这意味着接受 IEnumerable 或 IList,具体取决于您是否需要按索引访问它。

避免使用 ICollection 或 ICollection 作为参数只是为了访问 计数属性。

这样做的原因是,如果您需要 Count,您可能还需要按索引访问它。如果不是今天,那么明天。因此,请继续使用IList以防万一。

(我不确定我是否同意,但这确实有一定的意义。

简而言之,如何在 IEnumerable 上实现 ICollection?

简短的回答:.Count()扩展方法。确保导入 System.Linq。

长答案:

int count = 0;
if (x is ICollection)
    count = ((ICollection)x).Count;
else
    foreach (var c in x)
       count ++;
IEnumerable是一个

接口,ICollection也是如此。它是实现其中一个或两个的对象类型。您可以使用 obj is ICollection 检查对象是否实现了ICollection

例:

public class MyCollection<T> : IEnumerable<T>, ICollection<T>
{
    // ... Implemented methods
}
// ...
void Foo(IEnumerable<int> elements)
{
    int count;
    if (elements is ICollection<int>) {
        count = ((ICollection<int>)elements).Count;
    }
    else {
        // Use Linq to traverse the whole enumerable; less efficient, but correct
        count = elements.Count();
    }
}
// ...
MyCollection<int> myStuff;
Foo(myStuff);
ICollection不是

已经实现了IEnumerable吗?如果你需要一个集合,那么你需要一个集合。