[英]Search Generic C# List with Contravariant Type
想象一下我有這樣的課:
class MyKey : IComparable<MyKey> {
public int Key { get; private set; }
public MyKey(int key) { Key = key; }
public int CompareTo(MyKey that) {
return that.Key - this.Key;
}
}
此外,我有一個通用包裝類,如下所示:
class MyListWrapper<T> where T : MyKey
{
private List<T> list;
public MyListWrapper(IEnumerable<T> items)
{
list = new List<T>(items);
list.Sort();
}
public int Search(T searchKey)
{
return list.BinarySearch(searchKey);
}
}
這使人們可以存儲從MyKey
繼承的自定義類,並且效果很好。 但是,也可以使用MyKey
進行搜索,因為我們知道T
是MyKey
,並且列表是使用MyKey
的Key
排序的:
public int Search(MyKey searchKey)
{
return list.BinarySearch(searchKey); // Does not compile!
}
但是,由於BinarySearch
接受T
( T
可以是任何自定義類),因此無法編譯。
如果我提供比較器,它也不起作用。 想象一下MyKey
不可比,但是我做了一個使用Key
的自定義比較器。 我可以在排序和搜索時使用它。
可以使用MyKey
搜索列表嗎? 我不喜歡將列表存儲為List<MyKey>
並在使用它們時List<MyKey>
值(這違反了通用列表的目的)。 我也不能將類型List<T>
的List<MyKey>
為List<MyKey>
。
您可以創建一個繼承自MyNamedKey
的包裝器類,也可以創建MyNamedKey
本身的新實例,僅用於搜索項目。
var mySearchKey = new MyKey { Key = 2 };
var index = list.BinarySearch(new MyNamedKeyWrapper(mySearchKey));
class MyNamedKeyWrapper : MyNamedKey
{
public MyNamedKeyWrapper(MyKey key)
{
this.Key = key.Key;
}
}
這將幫助您維持O(log n),同時增加少量分配成本。
或者,如果您更喜歡使用脆性反射,則可以..獲取基礎數組的實例並將其Array.BinarySearch
為MyKey[]
(這是有效的,因為數組是協變的),並使用Array.BinarySearch
。
var array = (MyKey[])list.GetType()
.GetField("_items", BindingFlags.Instance | BindingFlags.NonPublic)
.GetValue(list);
var index = Array.BinarySearch(array, mySearchKey);
編輯:由於您不知道最派生的類型,如果您用通用參數約束new()
,則可以實現所需的功能
class MyListWrapper<T> where T : MyKey, new()
{
private readonly List<T> list;
public MyListWrapper(IEnumerable<T> items)
{
list = new List<T>(items);
list.Sort();
}
public int Search(MyKey searchKey)
{
T dummyKey = new T() { Key = searchKey.Key };
return list.BinarySearch(dummyKey);
}
}
Linq是您的追求!
首先,請確保您在使用中引用了System.Linq
。
然后,您可以使用以下代碼獲取所有匹配的列表項:
IEnumerable<MyNamedKey> found = list.Where(l => l.Key == 2);
要獲得單個物品,請使用:
MyNamedKey found = list.FirstOrDefault(l => l.Key == 2);
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.