Только быстро и коротко, на этот раз.Func
является контравариантным(РЕДАКТИРОВАТЬ:Параметр типа T равен ). Сейчас я работаю не с Func
, а с Expression
, и, кажется, зашел в тупик. ОБНОВЛЕНИЕ -ПРИМЕР ПОЛНОГО КОДА:
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- _items;
public IList
- Items
{
get
{
if (_items == null)
{
_items = new List
- ();
_items.Add(new Item() { Color = "black" });
_items.Add(new Item() { Color = "blue" });
_items.Add(new Item() { Color = "red" });
}
return _items;
}
}
public MainWindow()
{
InitializeComponent();
Expression
> filter = x => x.Color == "black";
Item i = Get(filter);
}
public Item Get(Expression> filter)
{
return Items.AsQueryable().Where(filter).FirstOrDefault();
}
}
Вызов выполняется с использованием Expression
в качестве аргумента и должен, если я правильно понял контравариантность, работать, потому что 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
:
public Item GetFunc(Func- filter)
{
return Items.AsQueryable().Where(filter).FirstOrDefault();
}
Как указано MS, это можно использовать с контравариантным параметром Type, как указано ниже:
Func filterFunc = x => x.Color == "black";
GetFunc(filterFunc);
Что снова заставляет меня задаться вопросом, почему это работает для Func
, но не для Expression
...
НАКОНЕЦ-ТО...
Проверенный ответ был выбран, потому что это то, что я в конечном итоге сделал. Как я сказал где-то в комментариях ниже,Get
-Метод использует NHibernate для получения данных. Но очевидно, что NHibernate имеет возможность принимать запросы через интерфейс и автоматически -выбирать типы, реализующие интерфейс. Это не решает саму проблему, но, как вы можете прочитать ниже, реального решения нет, поскольку то, что здесь встречается, было ожидаемым поведением.