当前位置: 首页 > 编程语言 > C#

IList一定要限制吗?共享

时间:2023-04-10 16:29:15 C#

IList必须是有限的吗?.NET的ILists必须是有限的吗?假设我编写了一个实现IList的FibonacciList类。我们现在已经实现了只读IList所需的所有方法,除了Count()。这很酷,还是对IList的滥用?斐波那契数列很快变得不切实际(因此出现了上面的IList)。有界无限序列可能更合理,它实现了IList或IList。附录二:斐波那契数列可能是一个不好的例子,因为计算远值的代价很高——要找到第n个值,你必须计算所有更早的值。因此,正如Mo?mondor所说,可以将其设为IEnumerable并使用.ElementAt。但是,存在其他序列,其中可以快速计算远距离值而无需计算较早的值。(令人惊讶的是,pi的数字是这样的序列)。这些序列更“强”,它们真正支持随机访问。编辑:没有人反对无限的IEnumerables。他们如何处理Count()?对于大多数开发人员而言,IList和ICollection意味着您可以使用预先评估的内存中集合。特别是IList,它有一个隐式常量Add*和一个索引操作契约。那是LinkedList没有实现IList。我认为FibonacciList违反了这个隐含的契约。请注意最近MSDN杂志文章中的以下段落,该文章讨论了将只读集合接口添加到.NET4.5的原因:对于大多数处理IEnumerable类型集合的场景来说就足够了,但有时您需要的不仅仅是它提供的多功能:正如其他人指出的那样,还有一个问题是您将为.Count返回什么。对此类数据集合使用IEnumerable或IQueryable是完全没问题的,因为这些类型的惰性评估是预期的。关于编辑1:.Count()不是由IEnumerable接口实现的:它是一种扩展方法。因此,开发人员需要预料到它可能需要任何时间,并且他们需要避免在实际上不需要知道项目数量的情况下调用它。例如,如果您只想知道IEnumerable是否有任何项目,最好使用.Any()。如果您知道要处理的项目数量最多,则可以使用.Take()。如果集合包含多个int.MaxValue项,.Count()将发生操作溢出。因此,有一些解决方法可以帮助减少与无限序列相关的危险。显然,如果程序员不考虑这些可能性,它仍然会导致问题。关于编辑2:如果您计划以索引为恒定时间的方式实现您的序列,那很容易解决我的观点。但是,Sixlettervararibles的回答仍然适用。*显然还有更多:IList.IsFixedSize只能在IList.IsFixedSize返回false时使用。仅当IsReadOnly返回false等时才可能进行修改。IList是一个经过深思熟虑的接口:这一事实最终通过在.NET4.5中引入只读集合接口得到解决。更新在给出一些额外的想法之后,我个人认为IEnumerable也不应该是无限的。除了实现类的.ToList()方法外,LINQ还有几个非流操作,例如.OrderBy(),它必须在返回第一个结果之前消耗整个IEnumerable。生成IEnumerable违反了里氏替换原则,因为许多方法都假定IEnumerable是完全可遍历的,而IEnumerable本身不受限制地遍历是不安全的。如果您发现您的应用程序经常需要斐波那契序列的片段作为IEnumerables,我建议创建一个方法,其签名类似于Enumerable.Range(int,int),允许用户定义开始和结束索引。如果您想启动一个Gee-Whiz项目,您可以想象开发一个基于Fibonacci的IQueryable提供程序,用户可以在其中使用LINQ查询语法的有限子集,如下所示://LINQtoFibonacci!varfibQuery=fromninFibonacci.Numbers//(返回一个IQueryable)wheren.Index>5&&n.Value由于您的查询提供者可以将where子句作为lambda表达式求值,因此您可以有足够的控制权来实现Count方法和.GetEnumerator()以确保查询具有足够的限制性以产生真实答案,或者在调用该方法后立即抛出异常。但这很聪明,对于任何真正的软件来说可能是一个非常糟糕的主意。我认为一致的实现必须是有限的,否则您会为ICollection.Count返回什么?//////获取.///整数计数{得到;另一个考虑因素是CopyTo,它在正常超载下永远不会停留在Fibonacci案例中。这意味着斐波那契数列的适当实现将是IEnumerable(使用生成器模式)。(Ab)使用IList只会导致问题。在您的情况下,我宁愿“违反”IEnumerable并让yield返回我的方式。?无限集合可能最好实现为IEnumerable而不是IList。您还可以在您的实现中使用yieldreturn语法,像这样(忽略溢出问题等):publicIEnumerableFib(){yieldreturn1;收益回报1;长l1=1;长l2=1;while(true){longt=l1;l1=l2;l2=t+l1;收益回报l2;正如@CodeInChaos在评论中指出的那样,IList的Item属性具有签名Tthis[intindex]{get;放;我们看到IList由整数索引,因此它们的长度受Int32.MaxValue限制。具有更大索引的元素将无法访问。这件事在我写这个问题时发生在我身上,但我把它留了下来,因为想想很有趣。编辑根据@StriplingWarrior的评论,请花一天时间来反思我的回答。恐怕得翻盘了。我昨晚开始尝试这个,现在我想知道放弃IList我到底失去了什么?我认为更明智的做法是实现IEnumerable,并声明一个本机Count()方法,该方法抛出NotSupportedException方法以防止枚举器运行,直到发生OutOfMemoryException。我仍然会添加一个IndexOf和Contains方法以及Item索引器属性来公开一个更高效的替代方案,例如Binet的公式,但是,我可以随意更改这些成员的签名以使用扩展数据类型,甚至是System.Numerics.BigInteger。如果我实现多个系列,我会为这些成员声明一个ISeries接口。谁知道,也许像这样的东西最终会成为框架的一部分。我不同意似乎已达成共识的观点。虽然IList有许多无法实现无限系列的成员,但它确实有一个IsReadOnly成员。对于ReadOnlyCollection,使用NotSupportedException实现大多数成员似乎是可以接受的。按照这个先例,如果这是对其他功能的副作用,我不明白为什么这是不可接受的。在这个特殊的Fibbonaci系列案例中,算法已经构建,请参见此处和此处,以短路正常的计数方法,我认为这会产生巨大的性能优势。通过IList公开这些好处对我来说似乎很有意义。理想情况下,.Net会支持一些其他更合适的超类接口,稍微接近IEnumerable,但是,在它出现在未来的某个版本中之前,这必须是一种明智的方法。我正在研究一个IList来说明总结我到目前为止所看到的内容:你可以做6个中的5个,在Count()上抛出NotSupportedException我想说这可能已经足够好了,但正如servy指出的那样,索引器是对于任何未计算和缓存的数字,效率都非常低。在这种情况下,我会说唯一适合您不断计算的合同是IEnumerable。您的另一个选择是创建一些看起来很像IList但实际上不是的东西。以上就是C#学习教程:IList一定要限制吗?如果分享的所有内容对您有用,需要了解更多C#学习教程,希望您多多关注---本文收集自网络,不代表立场。如涉及侵权,请点击右侧联系管理员删除。如需转载请注明出处: