C# の匿名型

C# 3.0 から匿名型 (anonymous types) が利用可能になりました。

通常 "データ型" というと int 型とか double 型などと指定するわけですが、それが匿名、名無し、というわけです。

匿名型とはどんなもので、どんなときに使うのか説明します。

C# の匿名型とは?

ここでは「匿名型」とは何か、ということを理解するためにまず、「匿名ではないもの」についてみてみましょう。

次のコードを見てください。

Person というクラスを定義して、そのオブジェクトを作成しています。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace AnonymousTypesTest1
{
  class Person
  {
    public string Name { get; set; }
    public int Age { get; set; }
  }

  class Program
  {
    static void Main(string[] args)
    {
      Person p = new Person()
      {
        Name = "Taro Yamada",
        Age = 30
      };

      Console.WriteLine("{0} ({1})", p.Name, p.Age);
    }
  }
}

この実行結果は次の通りです。

Taro Yamada (30)

new コンストラクタに続いて、初期値を入力する形式については 「オブジェクト初期化子」をみてください。

さて、ここで Person クラスは、Name と Age という二つのプロパティを定義するためだけに作られています。

Person (人) の情報として名前 (name) と年齢 (age) をひとまとめにして、ひとつのオブジェクトとして扱うためです。

中身は { get; set; } しか書いていません。これは自動実装プロパティ (Auto-Implemented Properties) です。

このように、データをひとまとめにして扱いたい場合は少なくありません。

そのたびに、クラスを事前定義しないといけないとなると、小さなクラスがたくさんできてしまって煩雑になる場合があります。

こうしたときに、匿名型を使うと便利です。

同様のことを匿名型を用いて実現してみましょう。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace AnonymousTypesTest2
{
  class Program
  {
    static void Main(string[] args)
    {
      var p = new
      {
        Name = "Taro Yamada",
        Age = 30
      };

      Console.WriteLine("{0} ({1})", p.Name, p.Age);
    }
  }
}

この実行結果はやはり次の通りになります。

Taro Yamada (30)

匿名型を利用したのは 12から16行目です。

オブジェクトを作成するために 「何か」 を new していますが、クラスの名前が記述されていません。

このように、事前に定義しておらず、 { } と属性の定義と値の代入を用いて作成されたオブジェクトを匿名型といいます。

匿名型は変数の宣言に型を書くことができないので、暗黙的型指定ローカル変数 var を用いて宣言します。

このように型の定義をあらかじめすることなく(従って名前も付いていない)、利用する型を匿名型といいます。

C# の匿名型の内部の名前

ちなみに試しに、型の情報を取り出す GetType() メソッドを使って、匿名型の名前を出力してみます。

Console.WriteLine("{0}", p.GetType().ToString());

結果は次の通り。

<>f__AnonymousType0`2[System.String,System.Int32]

このように、内部で機械的な名前が付けられていることがわかります。

LINQ にみる匿名型の利用

匿名型が活躍する例として LINQ での利用例をみておきましょう。

次の例を見てください。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace AnonymousTypesTest3
{
  class Program
  {
    class Person
    {
      public int Age { get; set; }
      public string Name { get; set; }
      public string City { get; set; }
    }

    static void Main(string[] args)
    {
      var p = new List<Person>() {
        new Person {
          Age = 10,
          Name = "Ichiro Suzuki",
          City = "Tokyo"
        },
        new Person {
          Age = 20,
          Name = "Hanako Yamada",
          City = "Sapporo"
        },
        new Person {
          Age = 35,
          Name = "Taro Yamada",
          City = "Yokohama"
        }
      };

      var s = from a in p
              where a.Age < 30
              select new
              {
                a.Name,
                a.City
              };

      foreach (var e in s)
      {
        Console.WriteLine("{0} [{1}]", e.Name, e.City);
      }
    }
  }
}

ここでは Person 型を定義してあり、 Person 型のコレクションがあります。

この中から条件 (Age < 30) によって特定の要素のみを抜き出し、興味のあるプロパティだけ、結果として取得したいと考えます。

このとき、結果を表すオブジェクトとして匿名型が使われます。(39-43行目)

また匿名型は名前が無いので、それを受ける変数は暗黙的な型指定ローカル変数の宣言として var を用いて、受け取ります。

以上、C# の匿名型について説明しました。

ここまでお読みいただき、誠にありがとうございます。SNS 等でこの記事をシェアしていただけますと、大変励みになります。どうぞよろしくお願いします。

© 2024 C# 入門