表达式中的方差<Func <T,bool >>

Seb*_*ier 5 c# covariance contravariance variance

这次只是一个快速而短暂的.Func<T,TResult> 是逆变的(编辑:类型参数T是).现在,我不与之合作Func<T,TResult>,而是与之合作Expression<Func<T,TResult>>,似乎已经走到了尽头.更新 - 完整代码示例:

public interface IColoredObject
{
    string Color { get; }
}

public class Item : IColoredObject
{
    public string Color { get; set; }

    public double Price { get; set; }
}

public partial class MainWindow : Window
{
    private IList<Item> _items;

    public IList<Item> Items
    {
        get
        {
            if (_items == null)
            {
                _items = new List<Item>();
                _items.Add(new Item() { Color = "black" });
                _items.Add(new Item() { Color = "blue" });
                _items.Add(new Item() { Color = "red" });
            }
            return _items;
        }
    }

    public MainWindow()
    {
        InitializeComponent();
        Expression<Func<IColoredObject, bool>> filter = x => x.Color == "black";
        Item i = Get(filter);
    }

    public Item Get(Expression<Func<Item, bool>> filter)
    {
        return Items.AsQueryable().Where(filter).FirstOrDefault();
    }
}
Run Code Online (Sandbox Code Playgroud)

使用Expression<Func<IColoredObject, bool>>as参数进行调用,如果我没有误解了逆变,则应该工作,因为IColoredObject它不是那样的Item.

我得到的是转换例外情况

无法转换

System.Linq.Expressions.Expression`1[System.Func`2[MyNs.IColoredObject,System.Boolean]]
Run Code Online (Sandbox Code Playgroud)

System.Linq.Expressions.Expression`1[System.Func`2[MyNs.Item,System.Boolean]]
Run Code Online (Sandbox Code Playgroud)

有没有办法解决这个问题并让它发挥作用?

编辑:

由于我所说的有些不准确,所以这里有更多背景资料.代码示例已更新.此外,我检查了MSDN所说的内容Func<T, TRes>:

public Item GetFunc(Func<Item, bool> filter)
{
    return Items.AsQueryable().Where(filter).FirstOrDefault();
}
Run Code Online (Sandbox Code Playgroud)

如MS所示,这可以与逆变型类型参数一起使用,如下所示:

 Func<IColoredObject, bool> filterFunc = x => x.Color == "black";
 GetFunc(filterFunc);
Run Code Online (Sandbox Code Playgroud)

这再次让我想知道为什么这适用于Func<T, TRes>但不适用于Expression<Func<T, TRes>>......

最后...

选中已选中的答案是因为这是我最终做的.正如我在下面的评论中所说,Get-Method利用NHibernate来获取数据.但显然NHibernate具有接受接口查询并自动选择实现接口的类型的功能.这并没有解决问题本身,但正如您可以在下面阅读的那样,没有真正的解决方案,因为这里遇到的是预期的行为.

Len*_*rri 2

这行:

public Item Get(Expression<Func<Item, bool>> filter) { /* ... */  }
Run Code Online (Sandbox Code Playgroud)

应该是:

public Item Get(Expression<Func<IColoredObject, bool>> filter) { /* ... */  }
Run Code Online (Sandbox Code Playgroud)

Get在这种情况下,如果您想调用传递方法,则必须使用接口Expression<Func<IColoredObject, bool>>