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具有接受接口查询并自动选择实现接口的类型的功能.这并没有解决问题本身,但正如您可以在下面阅读的那样,没有真正的解决方案,因为这里遇到的是预期的行为.
这行:
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>>。