如何在IEnumerable <t> </t> </t>上实现ICollection <t>

时间:2015-01-13 22:41:26

标签: c# linq collections

我想知道如何编写Microsoft建议的MSDN guidelines for collections,其中包含以下内容:

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?微软已经在该文章中提供了链接,但没有“这就是你如何做到这一点”的链接。

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

最初我将该集合作为IEnumerable返回。当我不需要分页时,这很方便。但是现在我面临着分页并且需要提取员工记录的数量才能做到这一点。一个解决方法是通过ref将employeeCount整数传递给我的getEmployeeRecords()方法并在该方法中分配值,但这只是一团糟。

根据我在StackOverflow上看到的内容,一般建议使用IEnumerable而不是ICollection,或Collection,或IList或List。所以我不是想打开关于那个话题的对话。 我想知道的是如何使IEnumerable实现ICollection,并提取记录数,以便我的代码更符合Microsoft的建议。一个代码示例或明确的文章证明这将是有帮助的。

感谢您的帮助!

4 个答案:

答案 0 :(得分:4)

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

答案 1 :(得分:2)

  

最初我将该集合作为IEnumerable返回。

那么你的问题就有一半了。返回类型应尽可能明确。如果您有一个集合,请创建该集合的返回类型。 (我忘记了哪里,但指南中提到了这一点。)

  

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

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

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

  

使用ICollection或ICollection作为参数进行AVOID访问   伯爵财产。

这样做的原因是,如果您需要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 ++;

答案 2 :(得分:1)

IEnumerable是一个界面,ICollection也是如此。它是实现一个或另一个或两者的对象类型。您可以使用ICollection检查对象是否实现obj is 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);

答案 3 :(得分:0)

不是ICollection已经实施IEnumerable了吗?如果您需要一个系列,那么您需要一个系列。