1

私は最近、クライアント用の IronRuby Web サービス アプリケーションを実装して、既存の C# .NET DLL を置き換えました。クライアントが言及するのを忘れていたのは、ラムダ式に基づく新しい API を使用して、その間に新しいバージョンの DLL を実装したことです。そして、すべての呼び出し (数千の :( ) が新しい構文を使用することを確認しました。そのため、Func/Actions を受信して​​リモート サーバーで実行する代替の .NET DLL を実装する必要があります。

現在、私は Ruby/Perl の専門家であり、高度な .NET についてほとんど知識がありません。式とランバの違いがよくわかりません。LINQ to SQL がリモート SQL サーバーで式を実行できることは知っています。ラムダも実行できますか? 私のシナリオで同じアプローチを (それが何であれ) 使用できますか?

一般的に、ポインタ/アイデア/解決策は大歓迎です。

ありがとう、フレデリック

4

1 に答える 1

2

あなたが何を求めているのか正確にはわかりません。Expressionしかし、少なくとも、メインストリームの .NET 言語 (C#、VB.NET) の言語機能であるラムダ関数とラムダ関数の違いについて、いくつかの洞察を提供することができます。


基本的に、ラムダ関数は、別の関数のスコープ内で宣言できる匿名 (名前のない) 関数です。C# (言語バージョン 3) では、次のように宣言されます。

   ( パラメータリスト 関数本体) => 

例えば:

void Foo()
{
    // two equivalent lambda functions with one double parameter 'x' each:
    var square = (double x) => x * x;
    var square2 = (double x) => { return x * x; };

    // lambda function that doesn't take any arguments:
    var doSomething = () => { Console.WriteLine("Hello."); }
}

(たとえば、ラムダ関数の名前ではなく、それを参照する変数の名前であることに注意してくださいsquare。ラムダ関数自体には、メソッドのような名前はありませんvoid Foo()!)

匿名デリゲートと呼ばれる、非常によく似たことが C# バージョン 2 で既に可能でした。

delegate(double x) { return x * x; }  // is equivalent to: (double x) => x * x

LINQ を使用して .NET にSystem.Linq.Expressionsが追加されました (名前空間内)。基本的に、 C# や VB.NET などで表現できるあらゆる計算を抽象構文木(AST)として記述する単純なデータ構造です。たとえば、次のとおりです。

// case 1. IEnumerable<int>:
IEnumerable<int> xs = ...;
IEnumerable<int> queryXs = from x in xs where x > 0 select x;

// case 2. IQueryable<int>:
IQueryable<int>  ys = ...;
IEnumerable<int> queryYs = from y in ys where y > 0 select y;

これら 2 つのクエリysは、タイプがIQueryable<int>ではなく であることを除いて、同じですIEnumerable<int>。C# コンパイラは、上記の 2 つのクエリを別のコードに変換します。

// case 1. IEnumerable<int>:
IQueryable<int> xs = ...;
IEnumerable<int> queryXs = xs.Where<int>(delegate (int x) { return x > 0; });

// case 2. IQueryable<int>:
IEnumerable<int> ys = ...;
ParameterExpression yParameter = Expression.Parameter(typeof(int), "y");
IEnumerable<int> queryYs.Where<int>(
    Expression.Lambda<Func<int, bool>>(
        Expression.GreaterThan(
            yParameter,
            Expression.Constant(0, typeof(int))),
        new ParameterExpression[] { yParameter }));

後者を調べると、 のクエリについてIQueryable<int>、コンパイラは解析されたクエリを、クエリを記述するデータ構造として出力したことがわかります。一方、 に対するクエリのIEnumerable<int>場合は、クエリを実行するコードを出力するだけです。コンパイラは、解析したものを式ツリーとして型だけで生成するという特別な魔法を実行することがわかりましたIQueryable<T>

式をIQueryable<T>使用すると、実行時にクエリを分析し、実際に実行する前に最適化やその他の変換を実行できます。これは、インテリジェントで最適化された SQL クエリを作成するために、LINQ to SQL などで頻繁に使用されます。

データベースが、一部の列xが > 0 であるすべての行を求められたと想像してください。

  • データベースがIEnumerable<int>(実際には大幅に単純化されていることはわかっていますが、ご容赦ください) の場合、すべての行を取得してから、.Where(delegate (int x) { ... })メソッドによってフィルター処理する必要があります。

  • データベースが の場合、IQueryable<int>コンパイラExpressionによる出力は実行時に分析され、SQL クエリに変換されます。これにより、適切なWHERE x > 0句が含まれ、必要な行のみがすぐに生成されます。


式ツリーの内部構造や構文解析に興味がある場合は、Bart De Smet による詳細なブログ シリーズを参照してください。最初はIQueryable tales - LINQ to LDAP - Part 0: Introductionです。

于 2010-07-14T19:50:11.227 に答える