[英]C# passing a compare class as a generic type
我是C#的新手。 我試圖創建一個堆結構,然后想到了一個問題:如何將“比較類”傳遞給堆結構? 我的意思是,我想創建一個堆: Heap<int, cmp<int>> heap = new Heap<int, cmp<int>>();
其中“ cmp”是一個比較類,它使堆按優先級順序排列(我在C ++中采用了priority_queue的思想)。 我成功地制作了一個使用最大-最小比較器的堆:
public class Heap<T, Priority>
where Priority : IPriority<T>, new()
where T : IComparable
{
private List<T> storage = new List<T>();
private Priority HeapPriority = new Priority();
private void UpHeap(int position)
{
for(var i = position; i > 0; i = (i - 1) >> 1)
{
// Check whether storage[i] is more Priority than storage[(i - 1) >> 1]
if (HeapPriority.MorePriority(storage[i], storage[(i - 1) >> 1])
.CompareTo(storage[i]) == 0)
{
storage.Swap(i, (i - 1) >> 1);
}
else break;
}
}
}
這是IPriority接口:
public interface IPriority<T>
where T : IComparable
{
T MorePriority(T a, T b);
}
我像這樣使用堆:
public class Min<T> : IPriority<T>
where T : IComparable
{
public Min() { }
public T MorePriority(T a, T b)
{
return a.CompareTo(b) <= 0 ? a : b;
}
}
static public void TestHeap()
{
var heap = new Heap<Pair<long, int>, Min<Pair<long, int>>>();
heap.Add(Pair<long, int>(10, 20));
heap.Add(Pair<long, int>(21, 100));
// ...
}
但是我想要一個堆,以我想要的任何方式對項目進行排序,而不僅僅是最大-最小順序。 而且,有沒有辦法將“ Ipriority.MorePriority”用作靜態方法?因為它的工作原理與靜態方法一樣。 誰能給我一些建議? 對不起,我的英語不好。
我建議將IComparer<T>
視為依賴項 ,並將其傳遞給構造函數; 像這樣的東西:
// You can create a heap of any type, right?
// But in some cases (e.g. Heap<Button>) you should provide a comparer:
// how to compare Button instances
public class Heap<T> {
//TODO: implement here Heap as well as Unheap method having IComparer<T> m_Comparer
...
private IComparer<T> m_Comparer;
// comparer = null - if comparer is not provided, try to use default one
// if it's possible (e.g. in case of Heap<double>)
public Heap(IComparer<T> comparer = null): base() {
// Do we have a default comparer (e.g. for int, double, string)?
if (null == comparer)
if (typeof(IComparable).IsAssignableFrom(typeof(T)) ||
typeof(IComparable<T>).IsAssignableFrom(typeof(T)))
comparer = Comparer<T>.Default;
if (null == comparer)
throw new ArgumentNullException("comparer", string.Format(
"There's no default comparer for {0} class, you should provide it explicitly.",
typeof(T).Name));
m_Comparer = comparer;
}
...
}
這樣就可以創建堆
// heap of integers, default comparer
Heap<int> heap1 = new Heap<int>();
// heap of integers, custom comparer (via lambda)
Heap<int> heap2 = new Heap<int>(Comparer<int>.Create((x, y) => -x.CompareTo(y)));
// heap of Buttons, custome comparer
Heap<Button> heap3 = new Heap<Button>(Comparer<Button>.Create((x, y) => ...));
這將引發異常 : Button
類沒有默認比較器
Heap<Button> heapErr = new Heap<Button>();
您應該只使用IComparer<T>
,這是.NET中所有集合所使用的。 例如:
public class Heap<T>
{
private IComparer<T> comparer;
private List<T> storage = new List<T>();
public Heap() : this(Comparer<T>.Default)
{
}
public Heap(IComparer<T> comparer)
{
this.comparer = comparer;
}
private void UpHeap(int position)
{
for(var i = position; i > 0; i = (i - 1) >> 1)
{
// Check whether storage[i] is more Priority than storage[(i - 1) >> 1]
if (comparer.Compare(storage[i], storage[(i - 1) >> 1]) > 0)
{
storage.Swap(i, (i - 1) >> 1);
}
else break;
}
}
}
這有幾個優點:
T
約束為IComparable
。 ICompatable
(如Int32
一樣),則Comparer<T>.Default
將使用該實現。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.