如何在 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 的建议。演示这一点的代码示例或清晰的文章将有所帮助。
感谢您的帮助!
需要注意的一点是,如果使用 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
吗?如果你需要一个集合,那么你需要一个集合。