表达式Func T,bool的方差是1. [英] Variance in Expression<Func<T,bool>>

查看:51
本文介绍了表达式Func T,bool的方差是1.的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

这次只是一个简短的演讲. Func< T,TResult> 是协变的( EDIT :类型参数T为).现在,我不使用 Func< T,TResult> ,而是使用 Expression< Func< T,TResult>> ,并且似乎已经死了结尾.更新-完整代码示例:

 公共接口IColoredObject{字符串颜色{get;}}公共类Item:IColoredObject{公共字符串Color {get;放;}公共双倍价格放;}}公共局部类MainWindow:Window{私有IList< Item>_项目;公共IList< Item>项目{得到{如果(_items == null){_items = new List< Item>();_items.Add(new Item(){Color ="black"});_items.Add(new Item(){Color ="blue"});_items.Add(new Item(){Color ="red"});}退换货品;}}公共MainWindow(){InitializeComponent();表达式< Func< IColoredObject,bool>过滤器= x =>x.Color ==黑色";项目i = Get(过滤器);}公共项目Get(Expression< Func< Item,bool>>过滤器){返回Items.AsQueryable().Where(filter).FirstOrDefault();}} 

该调用是使用 Expression< Func< IColoredObject,bool>> 作为参数进行的,并且,如果我没有误解矛盾的话,应该会起作用,因为 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> :

的看法.

 公共项GetFunc(Func< Item,bool>过滤器){返回Items.AsQueryable().Where(filter).FirstOrDefault();} 

如MS所示,可以将其与反型Type参数一起使用,如下所示:

  Func< IColoredObject,bool>filterFunc = x =>x.Color ==黑色";GetFunc(filterFunc); 

这又让我想知道为什么这对 Func< T,TRes> 有效,但不适用于 Expression< Func< T,TRes>> ... >

最终...

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

解决方案

此行:

 公共项Get(Expression< Func< Item,bool>>过滤器){/* ... */} 

应该是:

 公共项Get(Expression< Func< IColoredObject,bool>>过滤器){/* ... */} 

在这种情况下,如果要通过传递 Expression< Func< IColoredObject,bool>> 来调用 Get 方法,则必须使用该接口./p>

Just a quick and short one, this time. Func<T,TResult> is contravariant (EDIT : The Type Parameter T is). Now, I don't work with Func<T,TResult>, but rather with Expression<Func<T,TResult>>, and seem to have reached a dead end. UPDATE - FULL CODE SAMPLE :

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

The call is made using an Expression<Func<IColoredObject, bool>> as argument and should, if I haven't misunderstood contravariance, work, because IColoredObject is less derived that Item.

What I get is a conversion Exception saying something like

cannot convert

System.Linq.Expressions.Expression`1[System.Func`2[MyNs.IColoredObject,System.Boolean]]

To

System.Linq.Expressions.Expression`1[System.Func`2[MyNs.Item,System.Boolean]]

Is there any way of fixing this and getting it to work?

EDIT:

Since there's some inaccuracy in what I've said, here's more background. Code sample updated. Furthermore, I checked what MSDN said about Func<T, TRes>:

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

As indicated by MS, this can be used with a contravariant Type param, as listed below:

 Func<IColoredObject, bool> filterFunc = x => x.Color == "black";
 GetFunc(filterFunc);

Which again makes me wonder why this works for Func<T, TRes> but not for Expression<Func<T, TRes>>...

FINALLY...

The checked answer was selected because it is what I eventually did. As I said somewhere in the comments below, the Get-Method utilizes NHibernate to fetch data. But obviously NHibernate has a feature of accepting queries over an interface and auto-selecting the types that implement the interface. This does not solve the issue itself, but as you can read below, there is not real solution, since what encountered here was expected behaviour.

解决方案

This line:

public Item Get(Expression<Func<Item, bool>> filter) { /* ... */  }

shoud be:

public Item Get(Expression<Func<IColoredObject, bool>> filter) { /* ... */  }

You'll have to work with the interface in this case if you want to call the Get method passing Expression<Func<IColoredObject, bool>>.

这篇关于表达式Func T,bool的方差是1.的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆