web-dev-qa-db-ja.com

@ Html.DisplayFor(modelItem => item.FirstName)のラムダ式を理解したい

私はC#とMVCにかなり慣れており、匿名メソッドやLINQなどの特定の状況でラムダを使用しました。

通常、次のようなラムダ式が表示されます。

(x => x.Name), (x => { Console.WriteLine(x))

Lambda = "goes to"であることを理解しています。 leftパラメーターが使用されていないラムダ式を見たことはありません。

このラムダ式をどのように翻訳するかわかりませんが

@Html.DisplayFor(modelItem => item.FirstName)

誰も私のためにこれにいくつかの光を当てることができますか?これはいけません

(modelItem => modelItem.FirstName)?

これは、Microsoftの ASP.NET MVCチュートリアルの概要 から取得しました。

46
Jan Carlo Viray

ラムダ式は、匿名関数、つまり名前のない関数を記述する方法です。 「矢印」の左側にあるのは関数パラメーターであり、右側にあるのは関数本体です。したがって、_(x => x.Name)_は論理的にstring Function(Data x) { return x.Name }のようなものに変換されます。タイプstringおよびDataは明らかに変化し、コンテキストから派生します。

左側のパラメーターがないと、パラメーターのない関数に変換されるため、この_(() => someVariable)_は論理的に次のように変換されます:string Function() { return someVariable; }

この時点で、someVariableがどこから来たのか疑問に思うかもしれません。それは関数パラメーターではなく、関数で定義されていません。あなたは正しいでしょう、このような関数はコンパイルされません。ただし、このようなラムダ関数は、外側のスコープの変数を持ち上げてこの方法で使用できるため、まったく問題ありません。 (内部的には、ラムダ式で使用される変数がフィールドになるラッパークラスが作成されます。)

では、_model => item.FirstName_の意味を見てみましょう。論理的にはstring Function(Model model) { return item.FirstName; }に変換されます。基本的に、これはパラメーターを持つ関数ですが、このパラメーターは使用されません。

そして今、情報の最後のビット。ラムダ式は最終的に関数を表しますが、実際に実行されることを目的としてではなく作成される場合もあります(可能性はありますが)。ラムダ式は、式ツリーの形式で表すことができます。これは、実行する代わりにparsedにできることを意味します。

この特定の場合、MVCエンジンはrunラムダ式が表す関数ではありません。その代わり、式は解析済みであるため、MVCエンジンはこの特定の行に対してどのHTMLを発行するかを認識します。データ項目がモデルオブジェクトから直接取得されていない場合、ラムダ式の左側の部分は重要ではありません。

97
Andrew Savinykh

foreachループについてだと思います。例:

@foreach(var item in model) 
{ 
 <td> 
     @html.displayfor(model => item.firstName) </td>
 </td>     
}

var itemを使用する必要があるのは、シーケンス内の各アイテムが匿名型であるためです。 model => item.firstName 手段 (input parameter) => expression。現在の「アイテム」をitemに格納するため、入力パラメーターを使用できません。

6
varg

パラメーターなしのラムダを使用しています。こちらをご覧ください question

基本的にDisplayForはラムダ関数パラメーターモデルを使用せず(_または()を使用すると言うことができます)、forループ内でラムダ関数を使用してdisplayforを使用します。 DisplayForにはラムダ関数が必要です。

4
GraemeMiller

また、Visual Studioで生成されたコードを理解するのにも苦労しました。ラムダ式に関する一般的な説明を提供する代わりに、ASP.NET MVCフレームワークを使用してコンテキストを配置したいと思います。

2つの属性(CityとProvinceCode)を持つModelクラス(例:Destination)を準備したとします。

public class Destination
{
    public string City { get; set; }
    public string ProvinceCode { get; set; }
}

ControllerとViewを生成した後、前述のようにVisual Studioで生成されたコードを取得する必要があります。しかし、生成されたコードは、特にデータ行については理解がやや困難です

@Html.DisplayFor(modelItem => item.City)

私はちょうどguessHtmlヘルパークラスがcshtmlファイルで一貫して使用されるべきだとMVCチームが考えるべきだと思います。そのため、彼らはトリックを使用してC#コンパイラを渡そうとしました。この場合、modelItemはこのラムダ式の入力パラメーターとしても使用されません。タイプが[〜#〜] not [〜#〜]であるため、()は使用できません。そのため、modelまたは任意のモデルオブジェクトを置き換えると、ラムダ式が機能します。

正直に言うと、生成されたコードをより読みやすい形式に書き換えたいと思います。 Htmlヘルパークラスを使用する代わりに、次のように単純に正しい出力をレンダリングできます。

@foreach (var item in Model) {
<tr>        
    <td>  
        @* Code Generated by Visual Studio. modelItem is a dummy param *@
        @Html.DisplayFor(modelItem => item.City)
    </td>
    <td>
        @* A better way - simply get rid of Html helper class *@
        @item.ProvinceCode
    </td>
</tr>
}
1
Peter Chung