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. ラムダ式 | このブログの読者になる | 更新情報をチェックする
×

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