[英]Are there drawbacks to creating a class that encapsulates Generic Collection?
我的(C#3.0 .NET 3.5)應用程序的一部分需要維護幾個字符串列表。 我毫不奇怪地將它們聲明為List<string>
並且一切正常,這很好。
這些List
的字符串實際上(並且始終)是基金ID。 我想知道更明確的意圖是否更具意圖,例如:
public class FundIdList : List<string> { }
......這也有效。 從技術上還是哲學上來說,這有什么明顯的缺點嗎?
我將從另一個方向開始:將字符串包裝到名為FundId的類/結構中。 我認為,這樣做的優勢大於通用列表與專用列表。
至於FundIdList,擁有這樣一個類的優勢類似於FundId上面的第3點:你有一個地方可以掛鈎在FundIds列表上運行的方法/函數(即聚合函數)。 如果沒有這樣的地方,你會發現靜態幫助器方法開始在整個代碼中出現,或者在一些靜態助手類中出現。
List <>沒有虛擬或受保護的成員 - 這些類幾乎不應該是子類。 此外,雖然你可能需要List<string>
的全部功能,但如果你這樣做 - 是否有必要制作這樣的子類?
子類化有各種缺點。 如果您將本地類型聲明為FundIdList
,那么您將無法通過例如使用linq和.ToList
來分配它,因為您的類型更具體。 我看到人們決定在這些列表中需要額外的功能,然后將其添加到子類列表類中。 這是有問題的,因為List實現忽略了這些額外的位並且可能違反了你的約束 - 例如,如果你要求唯一性並聲明一個新的Add方法,那么任何人(例如)通過將列表作為一個簡單地(合法地)向上轉換為List<string>
任何人這樣輸入的參數將使用默認列表Add,而不是新的Add。 您只能添加功能,永遠不會刪除它 - 並且沒有需要子類化來利用的受保護或虛擬成員。
因此,您無法使用擴展方法添加任何功能,並且您的類型不再完全兼容,這限制了您可以對列表執行的操作。
我更喜歡聲明一個包含字符串的struct FundId
,並實現有關該字符串所需的任何保證,然后使用List<FundId>
而不是List<string>
。
最后,你真的是指List<>
嗎? 我看到很多人使用List<>
來處理IEnumerable<>
或plain數組更適合的事情。 在api中公開內部List
特別棘手,因為這意味着任何API用戶都可以添加/刪除/更改項目。 即使您首先復制列表,這樣的返回值仍然會產生誤導,因為人們可能希望能夠添加/刪除/更改項目。 如果您沒有在API中公開List
,而只是將其用於內部簿記,那么聲明和使用不添加任何功能的類型(僅文檔)並不是那么有趣。
僅對內部使用List<>
,如果這樣做,則不要將其子類化。 如果你想要一些顯式的類型安全,請在結構中包裝string
(不是類,因為結構在這里更有效並且具有更好的語義:在null的FundId
和空字符串之間沒有混淆,並且對象相等和哈希碼工作為預期結構但需要手動指定類)。 最后,如果您需要支持枚舉,或者如果您還需要索引,則使用簡單的ReadOnlyCollection<>
包裝器來展示IEnumerable<>
,而不是讓API客戶端使用內部位。 如果您確實需要可變列表API, ObservableCollection<>
至少可以讓您對客戶端所做的更改做出反應。
我個人會把它FundId
List<string>
,或者可能創建一個包裝字符串然后存儲List<FundId>
的FundId
類。
List<FundId>
選項將強制執行類型更正,並允許您對FundIds
進行一些驗證。
只需將其保留為List<string>
,您的變量名稱就足以告訴其他人它正在存儲FundID。
var fundIDList = new List<string>();
我什么時候需要繼承List<T>
?
如果您對基金ID列表有特殊的操作/操作,請繼承它。
public class FundIdList : List<string>
{
public void SpecialAction()
{
//can only do with a fund id list
//sorry I can't give an example :(
}
}
除非我想要某人做他們可以做的所有事情來List<string>
,而沒有對FundIdList
進行任何干預,我寧願實現IList<string>
(或者如果我不關心的話,可以實現層次結構更高層次的接口大多數接口的成員)並在適當時委托調用私有List<string>
。
如果我確實希望有人擁有這種程度的控制權,我可能只是首先給他們一個List<string>
。 據推測,你有一些東西可以確保這些字符串實際上是“基金ID”,當你公開使用繼承時,你不能再保證。
實際上,這聽起來(並且經常使用List<T>
)就像私有繼承的自然情況一樣。 唉,C#沒有私有繼承,所以組合是要走的路。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.