2010-04-04 40 views
2

我不清楚上面的說法。如果有人能解釋我們如何使用繼承來創建一個自定義的,類型安全的和無效的安全集合,那將會很棒。使用繼承來創建一個自定義的類型安全的null安全集合?

感謝

+0

你沒有明確的目標或實施?我問,因爲如果你不清楚目標,我們可以怎樣幫助你? 「無效安全」是什麼意思? – 2010-04-04 18:27:21

+0

我相信,我懷疑無意義的「無效安全」的普通術語是「不可空的」。我自己,我會以完全不同的方式使用「無效的安全」。 – 2010-04-04 18:36:45

回答

3

嗯,你可以從Collection<T>派生新類和重寫SetItemInsertItem:如果新值爲null拋出異常。這是你想要的那種東西嗎?

這將是:

  • 自定義:好,你要覆蓋方法來定製的正常行爲
  • 類型安全:由於從Collection<T>獲得的;基類防止被添加
  • 空安全不合適的類型的值:你的覆蓋將防止曾經存在收集

在空值你甚至可以把它通用:

// Note: you could include "where T : class"; on the other hand 
// you might have some reason to want a NullSafeCollection<int?> 
// which you knew had no null values in. 
public class NullSafeCollection<T> : Collection<T> 
{ 
    protected override InsertItem(int index, T item) 
    { 
     if (item == null) 
     { 
      throw new ArgumentNullException("item"); 
     } 
     base.InsertItem(index, item); 
    } 

    // Likewise for SetItem 
} 
+0

哦,不,Skeet是在房子裏,有任何一個upvote的機會,更不用說接受的答案 – 2010-04-04 18:32:18

+0

@Ben:那麼目前你有一個upvote,我沒有,所以... :) – 2010-04-04 18:34:22

2

我認爲問題在於模棱兩可的術語「無效安全」。

一般來說,對於類型安全集合,您將使用泛型,而不是繼承。

所以我想要的是一個派生的集合,它在一些標準的泛型集合之上添加了「空安全檢查」(不管你的情況如何)。除了在C#中的泛型集合不使用虛函數,所以它們不能被擴展(誰選擇這樣做,而不使這些類被封閉應該永遠被禁止編程)。

因此,您必須使用舊的.NET 1.x非泛型集合(如集合),並使用「類型安全檢查」和「空安全檢查」來覆蓋它們。

在另一方面,如果你在這個意義上我,然後是較常見的集合,如List<T>LinkedList<T>Stack<T>Queue<T>是已經在使用「空安全」,「空安全的」,因爲它們不死機或者如果您通過null則生成例外。另一方面,Dictionary<TKey,TValue>由於它在參數上調用GetHashCode,因此不是無效的。你必須修改它們來定義null的散列碼。 HashSet<T>實際上是這樣做的,將0定義爲null的散列。同樣,對於SortedList<TKey,TValue>SortedDictionary<TKey,TValue>,您必須定義排序順序中的null

據我所知,沒有辦法使這些集合行爲正確。在這些類中缺少null支持並不是由散列函數或比較器在傳入null時失敗引起的,它是由所有面向公衆的API中的先發制人檢查導致的。這些不能通過公共繼承來解決,而C#(通常.NET)不允許私有繼承。在光明的一面,System.Collections.ObjectModel.KeyedCollection<TKey,TItem>竭盡全力不讓空字符被底層字典看到。但它擴展了Dictionary<TKey,TValue>以通過遏制而不是繼承來增加無效安全。

+0

我認爲這是合理的推斷「無效安全集合」是防止添加空值的集合。我會說使用泛型和繼承是正交選擇。 – 2010-04-04 18:35:14

+0

不適用於'列表','LinkedList ','字典',以及任何其他通用集合,它們不提供用於覆蓋行爲的虛擬功能。當您將.NET與「所有繼承是公共」規則結合使用時,您無法執行其他不變量。當然,你指出的例外是System.Collections.ObjectModel泛型類。 – 2010-04-04 18:44:44

相關問題