今回は、簡単で短いものです。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には、インターフェースを介してクエリを受け入れ、インターフェースを実装するタイプを自動選択する機能があります。これは問題自体を解決するものではありませんが、以下で読むことができるように、ここで発生した動作は予期された動作であるため、実際の解決策はありません。