为什么我不能在扩展List的类中调用OrderBy?

问题描述:

我有一个类,Deck,其中包含一种称为Shuffle的方法。为什么我不能在扩展List的类中调用OrderBy?

我正在致力于重构Deck以扩展List<Card>,而不是将List<Card> Cards作为属性。然而,虽然Cards.OrderBy (a => Guid.NewGuid())工作,OrderBy (a => Guid.NewGuid())并不:

Error CS0103: The name 'OrderBy' does not exist in the current context (CS0103)

为什么这个不行?

+2

要理解为什么大家坚持不应该从'List '继承,请看这篇文章:http://blogs.msdn.com/kcwalina/archive/2005/09/26/474010.aspx实际上,虽然你从遗漏列表遗漏了一些东西(例如收藏修改的通知),但如果你没有在公共API中使用继承类,如果你想使用它,完全取决于你'列出'作为你的基础班。不是从'List '继承的是一个推荐,而不是一条硬性规则。 – 2010-01-27 02:02:41

+0

感谢您的链接,@Kyralessa。该建议似乎是一个很好的建议。继承列表首先是一个糟糕的主意,而列表不是被设计为继承的事实,这使得它变得更糟。 – 2010-01-27 02:13:29

this.OrderBy(a => Guid.NewGuid()); // a random ordering 

OrderBy添加this到的OrderBy前面作为是对IEnumerable<T>扩展方法,并且没有被List<T>的公共方法。如果在没有上下文的情况下键入OrderBy,编译器将查找名为OrderBy的实例或静态方法。只有在前缀OrderBy的实例为IEnumerable<T>时,编译器才会发现OrderBy。由于Deck : List<Card>List<Card> : IEnumerable<Card>,使用关键字this(对当前实例的引用)将为编译器提供定位方法Enumerable.OrderBy所需的上下文。

它被认为是bad practice to inherit from List<T> in a public API。首先,List<T>不是为继承而设计的,可能应该是sealed;现在太迟了。一般来说,当使用框架类时,你应该赞成使用继承。

+2

更正:从公共API *中继承'List '*被认为是不好的做法。如果继承类不是公共API的一部分,那么这不是问题。 – 2010-01-27 01:59:55

+2

+1感谢您发表最后一段!人们常常忽略这一点。我推荐Collection 或ObservableCollection 。 – Josh 2010-01-27 02:00:40

+0

@Kyralessa:感谢您的纠正! – jason 2010-01-27 02:03:42

OrderBy是一种扩展方法,因此它只能与IEnumerable<T>类型的限定符一起使用。您需要编写this.OrderBy。 (thisDeck类型,间接地继承IEnumerable<Card>的限定符)

注意OrderBy不是就地进行排序;如果要对现有实例进行排序,请致电Sort((a, b) => 2 - 2 * rand.Next(0, 1)),其中randRandom类的实例。


注意:这是bad practice to inherit List<T>。相反,你应该继承System.Collections.ObjectModel.Collection<T>

OrderBy不是List<T>上的方法 - 而是将其定义为扩展方法Enumerable.OrderBy

因为它不是类的方法,所以你需要让编译器看到这个。您可以通过拨打电话:

this.OrderBy(a => Guid.NewGuid());

但是,我建议您在这里重新考虑您的方法。子类List<T>是一个坏主意 - 通过封装List<T>实例来实现IList<T>要好得多。 List<T>应该是一个实现细节,而不是API本身的一部分。

+0

我认为你是对的(关于重新思考我的方法)。我注意到我正在'List'中重新实现几个方法/属性,比如'Count'。但我不想将我*不需要的所有方法与我所做的那些一起引入。用新方法包装我需要的方法非常简单。 – 2010-01-27 01:57:13