[英]Why doesn't LinkedList(T) implement the IList(T) interface?
在C#中,LinkedList(T)類不實現IList(T)接口。 但是,List(T)類確實實現了IList(T)。 為什么會出現這種差異? 從功能上講,它們都是列表,所以這個設計選擇看起來很奇怪。 現在很難將實現從List(T)切換到LinkedList(T)。
IList<T>
接口包含索引器,索引器不是您在LinkedList
上預期的功能。
List<T>
可以確保通過定義來訪問O(1) , LinkedList
的項目,它的結構不能提供對O(1)中項目的訪問。
查看鏈接列表的定義,您將理解。
主要問題,LinkedLists可以包含循環引用,因此沒有索引。
鏈表是最簡單和最常見的數據結構之一; 它們為幾個重要的抽象數據結構提供了簡單的實現,包括堆棧,隊列,關聯數組和符號表達式。
鏈接列表相對於傳統陣列的主要好處是鏈接項的順序可能與數據項存儲在內存或磁盤上的順序不同。 因此,鏈接列表允許在列表中的任何位置插入和刪除節點,並且操作數量恆定。
另一方面,鏈表本身不允許隨機訪問數據或任何形式的有效索引。 因此,許多基本操作 - 例如獲取列表的最后一個節點,或找到包含給定數據的節點,或定位應插入新節點的位置 - 可能需要掃描大多數列表元素。
接口給出了三種類型的保證,1種是程序性的,2種是概念性的。
程序保證是您可以調用存在的方法或屬性。 .NET強制執行此保證。
第一個概念保證是它會起作用。 這經常被破壞(NotImplementedException和NotSupportedException正好存在以打破這個),但應該有一個很好的理由這樣做。 不過,這更像是承諾而非保證。
第二個概念保證也是承諾而不是保證,即方法或財產將像其他情況一樣工作。
人們習慣於讓IList的索引器以相當快的速度運行 - O(1)或更糟糕的O(log n) - 並打破這個概念上的承諾會導致人們嚴重使用你的對象。
這里沒有具體的規則。 您當然可以將IList實現為鏈接列表,並且遭受O(n)索引獲取。 您還可以實現鏈接列表,使其不保留其計數記錄(由框架提供的記錄)並具有O(n)Count屬性。 但是人們更有可能使用它。
組件設計的一部分不僅僅是確保工作正常並且運行良好,而是指導它們的使用。 實現IList的鏈表在后一點會失敗,因此人們可以提出一個強有力的論據,即它不會像提供的那樣好。
LinkedList實際上是一個眾所周知的列表數據結構,具有以下操作復雜性:
Insertion: O(N)
Removal: O(1)
Indexing: O(N)
而List是一個連續數組,具有以下算法復雜性:
Insertion*: O(1)
Removal*: O(N)
Indexing: O(1)
它們不提供通用接口,因為它會誤導接口的用戶並使程序效率變得不可預測。 有關更多信息,請查看有關算法和數據結構的書籍。
LinkedList不是List。 列表是對象的單個維度集合。 LinkedList是一個節點集合,與Dictionary更緊密地對齊。 它的需求與常規List不相似,但更專業於允許節點遍歷和組織行為。
這也讓我感到意外。傳統上,列表只是你可以依賴元素順序的東西,鏈表遵循這個,它應該實現IList而不是ICollection(一個集合沒有說什么關於其元素的順序)。
由於某些操作的復雜程度低於某些人的預期,因此我沒有實現IList,這在我看來是錯誤的。
“列表”是數據結構術語不是鏈表; 它實際上是一個數組 - 使用索引器可以直接訪問列表項,索引器在鏈表中不可用(不實用)。
歷史怪癖:在.NET 1.1中,ArrayList是一個類似於動態長度數組的類。
在.NET 2+中,List內部組織為一個數組。 這意味着IList確實需要Array語義。
在.NET中,列表就像數組 ,而不是列表.... (boing)
真正的鏈接列表具有恆定的時間插入,刪除,但緩慢的枚舉和較慢的隨機訪問。
數組具有快速枚舉和隨機訪問,但具有昂貴的插入/刪除(O(n)和重新分配可能會導致完全不同的行為)
因為通過索引訪問鏈表不是O(1)。
鏈表不是設計為由索引訪問的數據結構,但IList<T>
提供索引訪問功能。
因此,由於您無法通過索引訪問鏈接列表中的項目,因此無法提供嘗試執行此操作的方法。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.