10

私はその内部動作を理解するのに本当に混乱していますこれはLINQ構文です

string[] test = new test[] { "abc", "", "cd", "", "aa" };
test = test.Where(x => !string.IsNullOrEmpty(x)).ToArray();

構文がどのように管理されるかについて混乱しています。すべての配列をxに入れますか?はいの場合、x null値をどのように管理しますか?

また

そうでない場合は、xに1つずつ配置された配列値をテストしますか?

4

3 に答える 3

10

残りの答えを検討する必要があります。それらはかなり正確です。私がお見せしたいのは、構文を理解するのに役立つかもしれません。この種のクエリは、実際には次のようなクエリ構文で表すことができます。

string[] test=new test[]{"abc","","cd","","aa"};

// this is the equivalent to your code
// added explicit type to make it clearer, it's optional
var a = from (string)x in test
        where !string.IsNullOrEmpty(x)
        select x;

SQLに精通している場合は、この構文がわかりやすく、知らない場合でも、この構文の方がわかりやすくなります。

コードがコンパイルされると、ILを生成するために、このクエリ構文は自動的にC#メソッド構文に変換されるため、DLLを分解すると、クエリ構文の代わりにメソッド構文が表示されます。

このコードについての簡単な説明:

  • ご覧のとおり、x変数が宣言されており、タイプはstringです。なんで?配列は文字列の配列であるため

  • は、反復in testするソース(この場合は配列)を示しますIEnumerable<>

  • これwhereはかなり説明的です。配列からnull以外のすべての文字列を選択するだけです。

  • そして最後に、実際にデータの投影である選択を行います。

そして、これはすべてあなたのコードと同等です

今、あなたは自分自身に問いかけているかもしれません...私はいつどちらかの構文を使うべきですか?それらは同等ですが、クエリ構文演算子は制限されています。つまり、ほとんどの操作はクエリ構文ではなくメソッド構文で実行されます。私がいつもしていることは、コードを読みやすくすることです。クエリ構文で記述されていると、コードが理解しやすくなります。

メソッド構文については、x => ...構文はラムダ式と呼ばれます。初めて使用する場合は奇妙に見えるかもしれませんが、最終的には気に入るはずです。

基本的にラムダはデリゲートへのショートカットなので、何をしているのか:

x => !string.IsNullOrEmpty(x)

匿名メソッドを作成していて、そのメソッドがデリゲートパラメーターに割り当てられています。はxを表しますstring variable

このトピックは、ここで説明するのに非常に広範囲ですが、これが背後にあるもののアイデアをあなたに与えてくれることを願っています。

ところで、次のような構文を組み合わせることができます。

// this is the equivalent to your code
// added explicit type to make it clearer, it's optional
var a = (from (string)x in test
        where !string.IsNullOrEmpty(x)
        select x).ToArray();

LINQをグーグルで検索するのは、ポルノのグーグルのようなものです。ウェブはLINQの記事やサンプルなどに悩まされています。

開始の良いポイントは、Microsoftからの101のサンプルです。

http://code.msdn.microsoft.com/101-LINQ-Samples-3fb9811b

編集

ラムダ式のより良い例が得られるように、Whereメソッドをエミュレートしようとします

// this is basically the declaration of one overload of the Where method
// the this in the parameter declaration, indicates this is an extension method which will be available to all IEnumerable<> objects
// the Func<T, bool> is the interesting part, it is basically a delegate (as a reminder, the last parameter of the Func object indicates the type that must be returned, in this case is a bool)
// the delegate is simply a pointer to a function 
public IEnumerable<T> Where<T>(this IEnumerable<T> source, Func<T, bool> predicate)
{

   ...some logic




   ... yielding back the reuslts
   foreach(var r in res)
   {
      // here is the delegate in action
       if(predicate(r))
           yield return r;
   }
}

ご覧のとおり、デリゲートは関数として呼び出されました(デリゲートは関数へのポインターです)しかし、どの関数ですか?コードで宣言したもの

  • x => !string.IsNullOrEmpty(x)xは、Whereメソッドから外部コードに返されるパラメーターを示します。ここでパラメーターを検査し、結果をフィルター処理するために使用できます。

  • x =>は、デリゲートを宣言するための略語です。

  • !string.IsNullOrEmpty(x)これは匿名メソッドの本体であり、bool(配列の要素をフィルター処理する述語)を返すという要件を満たしていることがわかりFunc<T, bool>ます。パラメーターとして、Tこの場合は配列からの文字列であるジェネリック

ラムダ式を宣言する別の方法は次のとおりです。

test = test.Where(
            (string) x =>
            {
                return !string.IsNullOrEmpty(x)
            })
           .ToArray();

この構文を使用すると、それらが実際にメソッド(匿名メソッド)であることを簡単に示すことができます。

于 2012-06-01T08:07:38.140 に答える
6

ステートメントを分解して、一度に1つずつ調べることができます

x => !string.IsNullOrEmpty(x)基本的に以下のような関数を定義しています

bool Filter(string x){
   return !string.IsNullOrEmpty(x)
}

そして、その関数に基づいて述語を作成します。述語は単なるデリゲートであり、変数に渡すことができる関数です。

.Where簡単にするために定義できる拡張メソッドです

IEnumerable<T> Where<T>(this IEnumerable<T> sequence,Predicate<T> pred){
   foreach(var elem in sequence){
       if(pred(elem)){
          yield return elem;
       }
   }
}

ラムダを使用する代わりに上記で定義されたように関数を定義した場合Filter、ステートメントは次のようになります

test = test.Where(Filter).ToArray(); 

したがって、配列でこの拡張メソッドを呼び出して上記の述語を渡すことにより、配列内のすべての要素を反復処理し、述語に一致するすべての要素(つまり、nullでも空の文字列の値でもない要素)を返します。

最後に、返された.ToArray()もの.WhereIEnumerable<string>)を配列に変換する拡張メソッドを呼び出します

于 2012-06-01T08:41:11.913 に答える
2

編集

この記事を読んで、あなたはきっとあなたが書いたということについて良い考えを得るでしょう......

C#3.0の新しい言語機能(パート1)

C#3.0の新しい言語機能(パート2)


これは、拡張メソッド+ C#3.0のラムダ式の部分からのものです

このコードでは

test=test.Where(x => !string.IsNullOrEmpty(x)).ToArray();

where-拡張メソッドです

x => !string.IsNullOrEmpty(x)-ラムダ式であり、無名関数の代わりになります

この関数全体は、配列の各要素をチェックします...つまり、lamdaba式は、配列の各要素が書き込まれた条件を満たしていることを確認し、最後に、条件を満たす要素の配列を再調整します。

于 2012-06-01T07:55:56.087 に答える