2009年10月31日

【var変数】 var変数記事一覧【まとめ】

C#3.0のvar変数に関する記事のまとめです。

1.【var変数】 新しい変数宣言var
  var変数とは?

2.【var変数】 varのメリット
  varはどのような場面で使うのが有効か?

3.【var変数】varが有効な場面
  varが特に有効と思われるパターンを紹介



次回は、yield return / yield breakについて書く予定です。
タグ:var変数
posted by 吾一 at 23:06| 3. var変数 | このブログの読者になる | 更新情報をチェックする

2009年10月27日

【var変数】varが有効な場面

前回のつづきになりますが、var変数が有効な場面をいくつか挙げてみます。
いずれも有効な場面と紹介されることが多いパターンですが、必ずvarを使ったほうが良い訳ではないです。
あくまで参考までに

for文のループ変数に使うパターン
class Program
{
    static void Main(string[] args)
    {
        for (var i = 0; i < 10; i++)
        {
             // 処理
        }
    }
}
varじゃなくて、intで良いじゃないかという意見は多いと思います。
タイプ数も同じだからあまり利点は無いのですが、ただ単にループすることが目的で、
変数iを一切参照しない場合には、型にこだわりが無いことが明確になるので良いかもしれません。

foreach文で使うパターン
class Program
{
    static void Main(string[] args)
    {
        // Dictionaryオブジェクトに値をセット
        Dictionary<int, string> dict = new Dictionary<int, string>();
        dict.Add(1, "一番");
        dict.Add(2, "二番");
        dict.Add(3, "三番");

        foreach (var kvp in dict)
        {
            // KeyとValueを表示
            Console.WriteLine(kvp.Key + kvp.Value);
        }
    }
}
結構おすすめに挙げられることが多いパターンです。
foreach文の見通しが良くなるのがメリットですね。
デメリットは、型が一見して分からなくなることです。
上の例のkvp変数は、本来KeyValuePair<int, string>型なのですが、これを長くて冗長だからvarとするか、
型が分かりにくいからKeyValuePair<int, string>と書くかは、どっちが良いか微妙なところです。
邪道ですが、列挙される型がすぐに分からない時に、一時的にvarと書いてIDEで型を確認するという使い方は有りだと思われます。

usingステートメントで使うパターン
class Program
{
    static void Main(string[] args)
    {
        // usingステートメントで、StreamWriterをnewして使用する
        using (var sw = new StreamWriter(@"log.txt", true, Encoding.GetEncoding("Shift_JIS")))
        {
            sw.WriteLine("ファイルに書き込み");
            sw.Close();
        }
    }
}
varを使わないとクラス名が2回繰り返されるパターンです。
見通しが良くなり、型も分かりにくくならないので積極的に使えそうです。
3つのパターンの中では一番おすすめです。

var変数の先頭記事へ var変数の次の記事へ
タグ:var変数
posted by 吾一 at 23:00| 3. var変数 | このブログの読者になる | 更新情報をチェックする

2009年10月24日

【var変数】 varのメリット

今回は、なぜvarを使うのか?どのような利点があるのか?を考察します。
実を言うとvarの使い方は、絶対の正解があるわけではないので少し難しいところです。
主な使い方を順番に見ていきましょう。

(1)組み込み型に対してvarを使う
class Program
{
    static void Main(string[] args)
    {
        // intの代わりにvarを使う
        var num = 100;
        // stringの代わりにvarを使う
        var str = "文字列";
    }
}
(2)クラス名に対してvarを使う
class Program   
{   
    static void Main(string[] args)   
    {   
        // List<int>の代わりにvarを使う
        var list = new List<int>();
        // StringBuilderの代わりにvarを使う
        var builder = new StringBuilder();
    }   
}
(3)匿名型に対してvarを使う
class Program
{
    static void Main(string[] args)
    {
        // 匿名型にvarを使う
        var Gogh = new { Name = "ゴッホ", Age = 37, Country = "オランダ" };
        var Monet = new { Name = "モネ", Age = 86, Country = "フランス" };
    }
}
匿名型というのは、クラス名を持たない匿名クラスのことです。
読み出し専用(getのみ)のプロパティだけで構成されるという特徴があります。
この匿名型を宣言する場合だけは、必ずvarで変数を宣言しなければなりません。
ここだけは、議論の余地が無く誰もが同じ書き方になります。

ただ(2)のクラス名の代わりにvarを使う書き方や、
(1)の組込型の代わりに使う書き方は人によって意見が大きく割れるところです。
class Program   
{   
    static void Main(string[] args)   
    {   
        // 通常の定義方法
        int a = 100;
        string b = "文字列";
        double c = 1.00d;
        
        // 組み込み型の代わりにvar
        var a = 100;
        var b = "文字列";
        var c = 1.00d;
    }   
}
組み込み型の代わりに使うvarは、結構抵抗がある人が多いみたいです。
今までの書き方に慣れている人にとっては、何のメリットがあるのか疑問に思いますよね。
メリットとしては、変数がvarで統一されてる方が変数名の位置が揃って見えるので、コードがスッキリ見えるところですね。
デメリットは、パッとコードを見た時に右辺の値を見ないと型が分からないのが若干手間に感じるところです。
あと一番大きいのが、今までの見慣れた書き方と掛け離れるって事だと思います。
個人的な考えでは、自分しか読まないコードなら組み込み型にvarを使うのもありだと思うのですが、
会社などチームで開発するなら、今のところは使わない方が無難かなと思います。(今後考えが変わる可能性はありますが)
class Program   
{   
    static void Main(string[] args)   
    {   
        // 通常の定義方法
        List<int> list = new List<int>();
        Dictionary<int, string> dict = new Dictionary<int, string>();
        StringBuilder builder = new StringBuilder();

        // クラス名の代わりにvar
        var list = new List<int>();
        var dict = new Dictionary<int, string>();
        var builder = new StringBuilder();
    }   
}
クラス名の代わりにvarを使うのはどうでしょうか?
通常の定義方法では、変数定義とnewの後で2箇所同じクラス名が出てくるので少し冗長な感じを受けますが、varの方はコードがスッキリして、メリットが際立ちます。
右辺を見れば、クラス名が書かれてますからデメリットもあまり目立たないような感じがします。
個人的に、この書き方は使っていった方が見やすくて良いかなと思うのですが、どうでしょうか。


いずれもvarの良し悪しは慣れによるところが大きいようですので、今後は全てvarで統一するような時代が来るのかも知れません。
他の方のブログとかを見てる感じでは、使っている内に違和感がなくなって考えが180度変わったという方が結構居ました。
変な先入観を持たずに、しばらく使ってみて判断するのが一番なのかもしれません。

var変数の先頭記事へ var変数の次の記事へ
タグ:var変数
posted by 吾一 at 23:26| 3. var変数 | このブログの読者になる | 更新情報をチェックする

2009年10月22日

【var変数】 新しい変数宣言var

今日から新しい章、var変数に入ります。
varとは、明示的に型名を書くことなく宣言できる変数宣言です。

class Program
{
    static void Main(string[] args)
    {
        // var変数の定義
        var num = 100;
        var str = "文字列";
    }
}
のように変数宣言して使います。
varには制限があり、ローカル変数でしか使うことが出来ません。
また、もう一つ重要な制限があります。
それは、varは必ず初期化と共に宣言されなければならないというものです。

class Program
{
    static void Main(string[] args)
    {
        // ↓これはコンパイルエラー
        var abc;
        //エラー CS0818: 暗黙的に型指定されたローカル変数を初期化しなければなりません
    }
}
varはなぜ必ず初期化しなければならないのでしょうか?
それは、var変数は宣言時に型を確定させなければならないからです。
つまりvar変数は、どんな型でも受け入れるVariant型ではなく
宣言時には必ずある特定の型に決定されます。
(初期化する値が整数であればint型、文字列ならstring型になる)
varが使用されていても、C#のコンパイル時の強力な型チェックは守られるのです。
見た目だけで判断すると、JavaScriptの変数の様に何でも代入できそうに見えますが、
実際は普通に宣言した変数と何ら変わらないということです。

class Program
{
    static void Main(string[] args)
    {
        // abcは int型に確定
        var abc = 100;
        
        // ↓これはコンパイルエラー
        abc = "文字列";
        // エラー CS0029: 型 'string' を型 'int' に暗黙的に変換できません。
    }
}
じゃあどういう場面で使うと便利なの?というのは次回に回すとして、
今回は、var変数の型が確定される仕組みを表したサンプルコードを示します。
以下のコードを御覧ください。

class Program
{
    static void Main(string[] args)
    {
        // aは int型
        var a = 0;
        // bは string型
        var b = "文字列";
        // cは object型
        var c = new object();

        // dは int型
        var d = 2147483647;    // int型の最大値
        // eは uint型
        var e = 2147483648;    // int型の最大値 + 1
        // fは int型
        var f = -2147483648;   // int型の最小値
        // gは long型
        var g = -2147483649;  // int型の最小値 - 1
        // hは long型
        var h = 9223372036854775807;  // long型の最大値
        // iは ulong型
        var i = 9223372036854775808;   // long型の最大値 + 1

        // jは float型(サフィックスがfまたはFの場合はfloat)
        var j = 1.0f;
        // kは double型(サフィックスがdまたはDの場合はdouble)
        var k = 1.0d;
        // lは decimal型(サフィックスがmまたはMの場合はdecimal)
        var l = 1.0m;
        // mは double型(サフィックスなしの実数はdouble)
        var m = 1.0;
    }
}
<暗黙的に確定される型の法則>
サフィックスの無い整数は、int、uint、long、ulongのうち、その値を表すことが出来る最初の型になる。
整数のサフィックスがUまたはuの場合、uintまたはulongのうち、その値を表すことが出来る最初の型になる。
整数のサフィックスがLまたはlの場合、longまたはulongのうち、その値を表すことが出来る最初の型になる。
整数のサフィックスがUL, Ul, uL, ul, LU, Lu, lU, またはluの場合、ulong型になる。
実数のサフィックスがFまたはfの場合、float型になる。
実数のサフィックスがDまたはdの場合、double型になる。
実数のサフィックスがMまたはmの場合、decimal型になる。


var変数の次の記事へ
タグ:var変数
posted by 吾一 at 01:06| 3. var変数 | このブログの読者になる | 更新情報をチェックする

2009年10月20日

【ラムダ式】 ラムダ式記事一覧【目次】

C#3.0のラムダ式に関する記事のまとめページです。

1.【ラムダ式】 はじめの一歩
  一番簡単なラムダ式の使い方

2.【ラムダ式】 ラムダ式のメリット
  ラムダ式はメソッドの処理内容をカスタマイズ出来る!

3.【ラムダ式】 定義済みデリゲート一覧
  .NET Frameworkで定義されている汎用デリゲート型一覧表

4.【ラムダ式】 上位スコープ変数の参照
  実質的にC#のクロージャと言えるラムダ式

5.【ラムダ式】 ThreadクラスとThreadStartデリゲート
  ラムダ式をThreadクラスで使用するには?

6.【ラムダ式】 ダミーのラムダ式
  何も処理しないラムダ式を書くには?

7.【ラムダ式】 汎用デリゲートの使い方
  よく使うAction<T>, Func<T>, Predicate<T>型の使い方をおさらい



次回からは、var変数について書く予定です。
今後ともよろしくお願いします。
タグ:ラムダ式
posted by 吾一 at 23:12| 2. ラムダ式 | このブログの読者になる | 更新情報をチェックする

2009年10月17日

【ラムダ式】 汎用デリゲートの使い方

ラムダ式の解説も終わりに近づいてきました。
今日はラムダ式に使える、汎用デリゲート型の一覧です。
ラムダ式の書き方のバリエーションと簡単な使い方をまとめました。
以下のコードを御覧ください。

class Program
{
    static void Main(string[] args)
    {
        // Func
        // 戻り値int  - 引数なし
        Func<int> func1 = () => 0;	
        // 戻り値int  - 引数(int)『引数の型を省略』
        Func<int, int> func2 = (x) => x * 2;
        // 戻り値int  - 引数(int)『引数の型を明示』
        Func<int, int> func3 = (int x) => x * 2;
        // 戻り値int  - 引数(int)『括弧を省略』
        Func<int, int> func4 = x => x * 2;
        // 戻り値int  - 引数(int)『ステートメント型』
        Func<int, int> func5 = (x) =>
        {
            return (x * 2);
        };
        // 戻り値string  - 引数(int, int, int, int)
        Func<int, int, int, int, string> func6 = (a, b, c, d) => (a + b + c + d).ToString();

        // Action
        // 戻り値void  - 引数なし『処理なしのラムダ式』
        Action action1 = () => { };
        // 戻り値void  - 引数なし
        Action action2 = () => Console.WriteLine("Hello!!");
        // 戻り値void  - 引数(string)
        Action<string> action3 = (message) => Console.WriteLine(message);
        // 戻り値void  - 引数(int, int, int, int)
        Action<int, int, int, int> action4 = (a, b, c, d) => Console.WriteLine(a + b + c + d);

        // Predicate<T>
        // 戻り値bool  - 引数(int)
        Predicate<int> predicate = (x) => x != 0;
        
        // MethodInvoker(using System.Windows.Forms;が必要)
        // 戻り値void  - 引数なし
        MethodInvoker invoker = () => Console.WriteLine("Hello!!");

        // Comparison<T> T型配列のソート
        int[] intArray = { 1, 10, 3, 2, 100, 5, 4 };
        Comparison<int> comparison = (x, y) => { return (x - y); };// 昇順
        Array.Sort(intArray, comparison);// ソート
        Array.ForEach(intArray, (x) => Console.Write("{0} ", x));// 結果表示
        Console.WriteLine();

        // Converter<TInput, TOutput> コレクションの各要素の型をTInput型からTOutput型に変換
        // Array クラスの ConvertAll メソッド、および List クラスの ConvertAll メソッドで使用される
        Converter<int, long> converter = (int x) => x * x;// int型→long型に変換するラムダ
        long[] longArray = Array.ConvertAll(intArray, converter);// long[]に変換
        Array.ForEach(longArray, (x) => Console.Write("{0} ", x));// 結果表示
    }
}
ラムダ式の引数が1つの場合に限り、括弧を省略できる。(上記のfunc4)
戻り値が無い場合は、ダミーのラムダ式を書ける。(上記のaction1)
Converter<TInput, TOutput>は、ArrayかListのConvertAll メソッドで使用する。(上記のconverter)
この辺りが少し分かりづらいですよね。

ラムダ式は上記の汎用デリゲート型以外にも、自分で定義した独自のデリゲート型が使えます。
デリゲート型名から使用方法が明確になるので、汎用デリゲートより独自デリゲートの方が良いのですが、
やはり定義せずに気軽に使えるのは大きいですね。
次回でラムダ式の記事は最後です。今まで出てきた特徴をまとめます。

ラムダ式の先頭記事へ
タグ:ラムダ式
posted by 吾一 at 22:50| 2. ラムダ式 | このブログの読者になる | 更新情報をチェックする

2009年10月15日

【ラムダ式】 ダミーのラムダ式

今日は簡単な話題で、何も処理を行わないダミーのラムダ式を紹介します。
ラムダ式は戻り値が無い場合に限り、処理なしのラムダ式を定義することが出来ます。
以下のコードを御覧ください。

class Program
{
    static void Main(string[] args)
    {
        // メッセージを表示する普通のラムダ式
        Action print = () => { Console.WriteLine("メッセージを表示する!!"); };
        print();

        // 何も行わないラムダ式
        Action dummy = () => { };
        dummy();

        Console.WriteLine("Main終了");

        // <結果>
        // メッセージを表示する!!
        // Main終了
    }
}
処理なしのラムダ式は、「 () => {}; 」という表記になります。
何もしない式なら必要無いのでは?と思われる方もいると思いますが、処理ありと処理なしを同一視することが出来ることが重要なポイントです。
テスト時などあえて処理をスキップさせたい場合に、ダミーのラムダ式を定義することで既存のコードを変更することなくダミーコードを実行することが可能になります。

ラムダ式の先頭記事へ ラムダ式の次の記事へ
タグ:ラムダ式
posted by 吾一 at 23:38| 2. ラムダ式 | このブログの読者になる | 更新情報をチェックする

2009年10月14日

【ラムダ式】 ThreadクラスとThreadStartデリゲート

前回の続きです。
今回は、ラムダ式が上位スコープの変数にアクセス出来ることを利用した実用的な例を示します。
Threadクラスは、別スレッドで処理するメソッドをThreadStartデリゲート型で受け取ります。
このThreadStartデリゲートにラムダ式を使用することが出来ます。
以下のコードを御覧ください。

class Program
{
    static void Main(string[] args)
    {
        string message = "スレッド内で表示する文字列:";
        // 別スレッドで処理するラムダ式
        ThreadStart action = () =>
        {
            for (int i = 0; i < 5; i++)
            {
                // 1秒スリープ
                Thread.Sleep(1000);
                // Mainメソッドのローカル変数を参照
                Console.WriteLine(message + i);
            }
            // Mainメソッドの引数を参照
            Console.WriteLine("argsの型={0}, argsのレングス={1}",
                                      args.ToString(), args.Length);
        };

        // スレッドクラスにThreadStartデリゲート(今回はラムダ式)を渡す
        Thread thread = new Thread(action);
        // スレッド開始
        thread.Start();
        // スレッド終了まで待つ
        thread.Join();

        // <結果>
        //スレッド内で表示する文字列:0
        //スレッド内で表示する文字列:1
        //スレッド内で表示する文字列:2
        //スレッド内で表示する文字列:3
        //スレッド内で表示する文字列:4
        //argsの型=System.String[], argsのレングス=0
    }
}
System.Threading名前空間のThreadStartデリゲートは、public delegate void ThreadStart ()と定義されており、これは引数なし、戻り値voidのメソッドのみ指定出来ることを意味しています。
Threadクラスには素直に引数を渡すことが出来ないので、パラメータを渡すのは多少工夫が必要です。
しかし、このThreadStartデリゲートにラムダ式を適用する事で、簡単にスレッド処理側にパラメータを渡すことが可能です。
上記のサンプルコードの例では、ラムダ式actionの中でMainメソッドのローカル変数messageとMainメソッドの引数argsを参照しています。
ラムダ式なら、引数として渡していない変数でもスレッド内で参照出来るのです。
サンプルの為に即興で考えたコードですが、今まであまり使ったことが無かったThreadクラスを一度使ってみたら面白いかなと思いました。

ラムダ式の先頭記事へ ラムダ式の次の記事へ
タグ:ラムダ式
posted by 吾一 at 00:12| 2. ラムダ式 | このブログの読者になる | 更新情報をチェックする

2009年10月11日

【ラムダ式】 上位スコープ変数の参照

ラムダ式は、名前の無い即席メソッドというだけでなくもう一つ重要な性質があります。
なんと、本来スコープ外であるはずの上位スコープの変数にアクセス出来るのです。
まずは、以下のコードを御覧ください。

class Program
{
    static void Main(string[] args)
    {
        // Mainのローカル変数
        int count = 0;
        // intを返すラムダ式の定義
        Func<int> getCount = () =>
        {
            // Mainのローカル変数を操作している
            count++;
            // インクリメントした値を返す
            return count;
        };

        // 引数にラムダ式を渡して実行
        PrintCounter(getCount);
        // 最後にPrintCounterメソッド実行後のcount値を表示
        Console.WriteLine("ローカル変数countの値={0}", count);

        // <結果>
        // ラムダ式の戻り値=1
        // ラムダ式の戻り値=2
        // ラムダ式の戻り値=3
        // ローカル変数countの値=3
    }

    static void PrintCounter(Func<int> getCount)
    {
        // ラムダ式を3回実行して、その戻り値を表示
        Console.WriteLine("ラムダ式の戻り値={0}", getCount());
        Console.WriteLine("ラムダ式の戻り値={0}", getCount());
        Console.WriteLine("ラムダ式の戻り値={0}", getCount());
    }
}
getCountは、引数なし、戻り値int型のラムダ式として定義されています。
このラムダ式から、本来スコープ外でアクセス出来ないはずのローカル変数countを操作しています。(最後にcountの値を表示してみても、確かにローカル変数の値が変更されていることが分かります)
実際順に処理を追ってみると、明らかに今までの常識外の動作であることが分かります。
まず、PrintCounterメソッドにgetCountラムダ式を引数として渡します。
PrintCounterメソッドでは、getCountを3回呼び出しますが、このラムダ式の中でMainメソッドのローカル変数であるcountを操作しています。
countを引数で渡していないにも関わらず、上位スコープのローカル変数の値を変更しているのです。
これは、オブジェクト指向の考えを覆すほどの大きな変化です。
オブジェクト指向では、GOF本等で書かれている通り、流動的要素をカプセル化する為に想定する変更箇所の外部インターフェースを事前に定義します。
つまり、抽象クラスやインターフェース(abstract classとinterface)をあらかじめ定義して、そのインターフェースに合うように具象クラスを作っていきます。
しかし、ラムダ式を使うことによってあらかじめ定義された引数以外の値すらメソッド内で操作出来るようになるのです。
このことは、事前に定義された外部インターフェースに縛られること無く、柔軟な拡張が行える可能性を秘めています。
次回は、この性質を使った実用的な例を解説します。

ラムダ式の先頭記事へ ラムダ式の次の記事へ
タグ:ラムダ式
posted by 吾一 at 23:55| 2. ラムダ式 | このブログの読者になる | 更新情報をチェックする

2009年10月10日

【ラムダ式】 定義済みデリゲート一覧

今回は定義済みデリゲートのお話です。
定義済みデリゲートとは、クラスライブラリで定義されているラムダ式を格納出来る型のことです。
前回までのサンプルコードでは、Actionデリゲート型のみを使用しましたが、
.NET FrameworkにはAction以外にもラムダ式に使用できる型が定義されています。
以下のコードを御覧ください。
class Program
{
    static void Main(string[] args)
    {
        // string型の引数1つ、戻り値voidのラムダ式
        Action<string> lambda1 = (string message) => /* 括弧の中に型を明示しても良い */
        {
            // 引数で受け取った文字列を表示
            Console.WriteLine(message);
        };

        // string型の引数1つを受け取り、int型の戻り値を返すラムダ式
        Func<string, int> lambda2 = (message) =>
        {
            Console.WriteLine(message);
            // int型を返す
            return 0;
        };

        // string型の引数1つを受け取り、bool型の戻り値を返すラムダ式
        Predicate<string> lambda3 = (message) =>
        {
            Console.WriteLine(message);
            // bool型を返す
            return true;
        };

        // 引数なし、戻り値voidのラムダ式を呼び出し( void lambda1(string)の呼び出しと同じ )
        lambda1("ラムダ式に引数を渡して実行!");

        // 引数1つ、戻り値intのラムダ式を呼び出し( int lambda2(string)の呼び出しと同じ )
        int retInt = lambda2("ラムダ式に引数を渡し、int型の戻り値を受け取る!");
        Console.WriteLine("lambda2の戻り値=" + retInt);

        // 引数1つ、戻り値boolのラムダ式を呼び出し( bool lambda3(string)の呼び出しと同じ )
        bool retBool = lambda3("ラムダ式に引数を渡し、bool型の戻り値を受け取る!");
        Console.WriteLine("lambda3の戻り値=" + retBool);

        // <結果>
        // ラムダ式に引数を渡して実行!
        // ラムダ式に引数を渡し、int型の戻り値を受け取る!
        // lambda2の戻り値=0
        // ラムダ式に引数を渡し、bool型の戻り値を受け取る!
        // lambda3の戻り値=True
    }
}
Action<string>型は、引数がstring、戻り値がvoidのラムダ式を代入可能です。
Func<string, int>型は、引数がstring、戻り値がintのラムダ式を代入可能です。
Predicate<string>型は、引数がstring、戻り値がboolになるラムダ式を代入可能です。
Action<T>、Func<T, TResult>、Predicate<T>は、それぞれTの部分に任意の型が指定出来るジェネリックデリゲートと呼ばれるものです。
デリゲート型の変数には、型が一致するラムダ式を代入することが出来ます。(=引数と戻り値の型が全く同じメソッドのみ代入出来るということ)
これらは、.NET Frameworkにて標準で用意されているものなのでいつでも自由に使うことが出来ます。

以下、定義済みデリゲートの一覧です。
.NETバージョン 備考
MethodInvoker 引数:なし
戻り値:void
1.0 プロジェクトの参照設定でSystem.Windows.Forms.dllを追加する必要がある。
Action 引数:なし
戻り値:void
3.5 MethodInvokerよりはこちらを使うほうが良い
Action<T> 引数:任意の型1個
戻り値:void
2.0 Tには引数の型を指定する
Action<T1, T2>
Action<T1, T2, T3>
Action<T1, T2, T3, T4>
引数:任意の型2〜4個
戻り値:void
3.5 T1〜T4には引数の型を指定する
Func<TResult>
Func<T, TResult>
Func<T1, T2, TResult>
Func<T1, T2, T3, TResult>
Func<T1, T2, T3, T4, TResult>
引数:任意の型0〜4個
戻り値:任意の型
3.5 TResultは戻り値の型、T1〜T4には引数の型を指定する
Predicate<T> 引数:任意の型1個
戻り値:bool
2.0 戻り値は暗黙的にbool
Comparison<T> 引数:任意の型2個
戻り値:int
2.0 Sortなどでの比較用デリゲート
Converter<TInput, TOutput> 引数:任意の型1個
戻り値:TOutput
2.0 特定の型のオブジェクトを別の型のオブジェクトに変換

上記の定義済みデリゲート以外にも、自分で任意のデリゲート型を定義してラムダ式を代入することも出来ます。
ただ、これらの汎用的なデリゲートを使えば定義を省けるので楽出来るというわけですね。

ラムダ式の先頭記事へ ラムダ式の次の記事へ
タグ:ラムダ式
posted by 吾一 at 23:13| 2. ラムダ式 | このブログの読者になる | 更新情報をチェックする
×

この広告は1年以上新しい記事の投稿がないブログに表示されております。