无法将lambda表达式转换为委托类型&#39; System.Func <t,tkey>&#39;

时间:2016-07-22 23:52:45

标签: c# generics

我正在为min heap编写一个泛型类,我希望能够在TKey以及T上进行堆积。

interface IHeap<T, TKey>
    where TKey : IComparable<TKey>
{
    void Insert(T x);
    T Delete();
    T Top();
}

public class MinHeap<T, TKey> : IHeap<T, TKey>
    where TKey : IComparable<TKey>
{
    public MinHeap(int capacity)
        : this(capacity, x => x) // <---- compilation error here
    { }
    public MinHeap(int capacity, Func<T, TKey> keySelector)
        : this(capacity, keySelector, Comparer<TKey>.Default)
    { }
    public MinHeap(int capacity, Func<T, TKey> keySelector, IComparer<TKey> comparer)
    {
        // ...
    }
    // ...
}

我为x => x收到了这些编译错误:

Cannot convert lambda expression to delegate type 'System.Func<T,TKey>' because some of the return types in the block are not implicitly convertible to the delegate return type.
Cannot implicitly convert type 'T' to 'TKey'

我如何实现这一目标并且只有一个班级?

更新

我希望能够做两件事:

// 1
var minheap = new MinHeap<Person, int>(10, x => x.Age);

// 2
var minheap = new MinHeap<int>(10);
// instead of 
var minheap = new MinHeap<int, int>(10, x => x);

3 个答案:

答案 0 :(得分:2)

x => xFunc<T, T>,而不是您其他构造函数中所需的Func<T, TKey>

你需要有一个默认的选择器,或者更好的是我会禁止那个构造函数并强制用户在实例化类时提供一个键选择器。

答案 1 :(得分:2)

可以使用与约束匹配的任何泛型类型参数来实例化

MinHeap<T,TKey>

这意味着,例如,您可以拥有MinHeap<string,int>。在这种情况下,您将尝试将lambda x => x分配给Func<string,int>,这不起作用,因为它是Func<string,string>

我认为没有一种明智的方法来实现你想要的东西,因为没有一个好的候选者可以将一种任意类型转换为另一种任意类型的“默认”方式,这就是你所需要的。

您可以做的是删除此构造函数并添加一个静态构造函数,该构造函数可用于TTKey类型相同的情况:

public static class MinHeap
{
    public static MinHeap<T,T> Create<T>(int capacity) where T : IComparable<T>
    {
        return new MinHeap<T,T>(capacity, x => x);
    }
}

但如果这还不足以满足您的需求,那么只需删除构造函数并接受人们将不得不处理传递lambda的问题。

答案 2 :(得分:-1)

我将我的答案添加为

  1. 尽管给予了,但很少有人不明白我想做什么 一个例子。
  2. 没有人提到这个答案。
  3. 我从MinHeap<T, TKey>删除了构造函数。我定义了另一个类如下。

    public class MinHeap<T> : MinHeap<T, T>
        where T : IComparable<T>
    {
        public MinHeap(int capacity)
            : this(capacity, Comparer<T>.Default)
        { }
        public MinHeap(int capacity, IComparer<T> comparer)
            : base(capacity, x => x, comparer)
        { }
    }