这次只是一个快速而简短的。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();
}
}
该调用是使用Expression<Func<IColoredObject, bool>>
as 参数进行的,如果我没有误解逆变性,应该可以工作,因为.IColoredObject
Item
我得到的是一个转换异常,说的是
无法转换
System.Linq.Expressions.Expression`1[System.Func`2[MyNs.IColoredObject,System.Boolean]]
至
System.Linq.Expressions.Expression`1[System.Func`2[MyNs.Item,System.Boolean]]
有没有办法解决这个问题并让它工作?
编辑:
由于我所说的有些不准确,这里有更多的背景。代码示例已更新。此外,我检查了 MSDN 所说的Func<T, TRes>
:
public Item GetFunc(Func<Item, bool> filter)
{
return Items.AsQueryable().Where(filter).FirstOrDefault();
}
如 MS 所示,这可以与逆变类型参数一起使用,如下所示:
Func<IColoredObject, bool> filterFunc = x => x.Color == "black";
GetFunc(filterFunc);
这再次让我想知道为什么这适用于Func<T, TRes>
但不适用于Expression<Func<T, TRes>>
......
最后...
选择了选中的答案,因为这是我最终所做的。正如我在下面的评论中所说的那样,Get
-Method 利用 NHibernate 来获取数据。但显然 NHibernate 具有接受接口查询并自动选择实现该接口的类型的功能。这本身并不能解决问题,但正如您在下面看到的那样,没有真正的解决方案,因为这里遇到的是预期的行为。