简体   繁体   English

C#将比较类作为通用类型传递

[英]C# passing a compare class as a generic type

I'm new in C#. 我是C#的新手。 I tried to create a heap structure and I came up with this question: How do I pass a "compare-class" to my heap structure? 我试图创建一个堆结构,然后想到了一个问题:如何将“比较类”传递给堆结构? I mean, I want to create a heap like: Heap<int, cmp<int>> heap = new Heap<int, cmp<int>>(); 我的意思是,我想创建一个堆: Heap<int, cmp<int>> heap = new Heap<int, cmp<int>>(); where "cmp" is a compare-class which makes the heap in a priority order (I took the idea of priority_queue in C++). 其中“ cmp”是一个比较类,它使堆按优先级顺序排列(我在C ++中采用了priority_queue的思想)。 I have succeed (I think) in making a Heap that takes a max-min comparer: 我成功地制作了一个使用最大-最小比较器的堆:

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;
        }
    }   
}

and here is the IPriority interface: 这是IPriority接口:

public interface IPriority<T>
    where T : IComparable
{
    T MorePriority(T a, T b);
}

and I used the Heap like this: 我像这样使用堆:

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));
        // ...
    }

but I want a heap that sorts the items by any way that I want, not only max-min order. 但是我想要一个堆,以我想要的任何方式对项目进行排序,而不仅仅是最大-最小顺序。 Moreover, is there a way to use "Ipriority.MorePriority" as a static method?, because it's working just like a static method. 而且,有没有办法将“ Ipriority.MorePriority”用作静态方法?因为它的工作原理与静态方法一样。 Can anyone give me some advices? 谁能给我一些建议? Sorry for my bad English. 对不起,我的英语不好。

I suggest treating IComparer<T> as a dependence and pass it to constructor; 我建议将IComparer<T>视为依赖项 ,并将其传递给构造函数; something like this: 像这样的东西:

  // 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;
    }
    ...
  }

So you can create heaps 这样就可以创建堆

  // 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) => ...));

And this will throw exception : no default comparer for Button class 这将引发异常Button类没有默认比较器

  Heap<Button> heapErr = new Heap<Button>();

You should just use IComparer<T> , which is what all the collections in .NET use. 您应该只使用IComparer<T> ,这是.NET中所有集合所使用的。 For example: 例如:

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;
        }
    }   
}

This has several advantages: 这有几个优点:

  • You don't need the extra type parameter for the comparer, which is a lot more convenient when referencing the heap in other methods. 您不需要比较器的额外类型参数,在其他方法中引用堆时,这会方便得多。
  • There's no need to constrain T to be IComparable . 无需将T约束为IComparable
  • However, if it does implement ICompatable (like Int32 does), Comparer<T>.Default will use that implementation. 但是,如果它确实实现了ICompatable (如Int32一样),则Comparer<T>.Default将使用该实现。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM