2

今週は式ツリーで遊んでいますが、この式を実行するとエラーが発生するのはなぜだろうかと思っています。

var pe = Expression.Parameter(typeof(Nullable<DateTime>));

var ex = Expression.Lambda<Func<DateTime?, bool>>(
   (Expression<Func<DateTime?, bool>>) (x => x.HasValue), pe);

この背後にある考え方は、式ツリー API と linq 式を組み合わせて式ツリーを作成することです。Expression.Property(...,..)たとえば、 I will have just haveを呼び出す代わりに、物事を書くのが簡単になりx => x.Propますよね?

これの代わりに私の例では、これExpression.Property(..hasvalue..)があります: x.HasValue. 書く時間を節約できますし、見た目も短くなりますよね?

問題は、これが可能かどうかです。

私は何かが欠けているかもしれないと思います

Expression<Func<DateTime?, bool>> foo = x => x.HasValue (this works)

Func<DateTime?, bool> bar = x => x.HasValue (this works too)

二人の背後で何が起きているのか? 彼らは同じですか?

linq式は標準の式ツリーAPIと混在できますか???

これについて教えてください、私は迷っています。:)

4

1 に答える 1

1

これは良い質問です。あなたの2つの引用

Expression<Func<DateTime?, bool>> foo = x => x.HasValue

Func<DateTime?, bool> bar = x => x.HasValue

ホモイコニシティの例です:同じシンボル(あなたの場合は x => x.HasValue)は2つの非常に異なるオブジェクトを表します。最初のケースでは、式ツリーを示します。2 番目は関数です。前者は後者にまとめることができますが、それらは異なる目的を持つ異なるタイプです。コンパイラにどのバージョンを使用するかを伝えるのは、あなたの場合の宣言です。このコンテキストがないと、コンパイラはあなたの心を読むことができず、代わりに救済することを決定します。そのため、これはコンパイルされません:

var bat = x => x.HasValue;

それがあなたのステートメントがコンパイルされない理由です。

ホモイコニシティがIQueryableIEnumerableをとても似たものにしています。呼び出すとき

var filteredCollection = myCollection.Where(e => e.IsActive);

実際には、のタイプに応じて異なる署名でメソッドを呼び出していますfilteredCollectionFunc<MyClass, bool>forIEnumerableExpression<Func<MyClass, bool>>for ですIQueryable)。

あなたの特定の状況に関しては、あなたがやりたいことを直接達成することはできませんが、卑劣な拡張メソッドを書くと:

public static class ExpressionExtensions
{
    public static Expression<Func<T, TProperty>> Lambda<T, TProperty>(this ParameterExpression pe, Expression<Func<T, TProperty>> property)
    {
        return Expression.Lambda<Func<T, TProperty>>(property, pe);
    }
}

次に、これを行うことができます:

var pe = Expression.Parameter(typeof(DateTime?));
var ex = pe.Lambda<DateTime?, bool>(x => x.HasValue);
于 2013-11-12T14:59:42.133 に答える