2010-01-27 119 views
2

我有一個類,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

回答

8

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

3

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>

1

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

相關問題