方法 : グループ化結合を実行する (C# プログラミング ガイド)

更新 : 2007 年 11 月

グループ化結合は、階層データ構造を作成する場合に便利です。グループ化結合は、最初のコレクションの各要素と、2 番目のコレクションの相関関係を持つ要素のセットを組み合わせたものです。

たとえば、Student という名前のクラスまたはリレーショナル データベース テーブルに、Id と Name の 2 つのフィールドがあるとします。また、Course という名前の 2 番目のクラスまたはリレーショナル データベース テーブルに、StudentId と CourseTitle の 2 つのフィールドがあるとします。一致する Student.Id と Course.StudentId に基づいて、これらのデータ ソースのグループ化結合を行うと、Course オブジェクトのコレクションを持つ各 Student がグループ化されます (コレクションは空の場合もあります)。

Bb397905.alert_note(ja-jp,VS.90).gifメモ :

最初のコレクションの各要素は、2 番目のコレクションに相関関係を持つ要素があるかどうかに関係なく、グループ化結合の結果セットに表示されます。相関関係を持つ要素が見つからない場合、その要素の相関関係を持つ要素のシーケンスは空になります。したがって、結果セレクタは最初のコレクションのすべての要素にアクセスできます。これは、非グループ化結合の結果セレクタとは異なります。非グループ化結合の結果セレクタは、2 番目のコレクションに一致するものがない最初のコレクションの要素にアクセスすることはできません。

このトピックの最初の例では、グループ化結合を実行する方法を示します。2 番目の例では、グループ化結合を使用して XML 要素を作成する方法を示します。

使用例

グループ化結合の例

Pet.Owner プロパティと一致する Person に基づいて、Person オブジェクトと Pet オブジェクトの型のグループ化結合を行う例を次に示します。一致ごとにペアを作成する非グループ化結合と異なり、グループ化結合では、最初のコレクションの要素ごとに 1 つのオブジェクト (この例では Person オブジェクト) のみを作成します。次に、2 番目のコレクションの対応する要素 (この例では Pet オブジェクト) がコレクションにグループ化されます。最後に、結果セレクタ機能により、Person.FirstName と Pet オブジェクトのコレクションで構成される一致ごとに匿名型が作成されます。

class Person
{
    public string FirstName { get; set; }
    public string LastName { get; set; }
}

class Pet
{
    public string Name { get; set; }
    public Person Owner { get; set; }
}

/// <summary>
/// This example performs a grouped join.
/// </summary>
public static void GroupJoinExample()
{
    Person magnus = new Person { FirstName = "Magnus", LastName = "Hedlund" };
    Person terry = new Person { FirstName = "Terry", LastName = "Adams" };
    Person charlotte = new Person { FirstName = "Charlotte", LastName = "Weiss" };
    Person arlene = new Person { FirstName = "Arlene", LastName = "Huff" };

    Pet barley = new Pet { Name = "Barley", Owner = terry };
    Pet boots = new Pet { Name = "Boots", Owner = terry };
    Pet whiskers = new Pet { Name = "Whiskers", Owner = charlotte };
    Pet bluemoon = new Pet { Name = "Blue Moon", Owner = terry };
    Pet daisy = new Pet { Name = "Daisy", Owner = magnus };

    // Create two lists.
    List<Person> people = new List<Person> { magnus, terry, charlotte, arlene };
    List<Pet> pets = new List<Pet> { barley, boots, whiskers, bluemoon, daisy };

    // Create a list where each element is an anonymous type
    // that contains the person's first name and a collection of 
    // pets that are owned by them.
    var query = from person in people
                join pet in pets on person equals pet.Owner into gj
                select new { OwnerName = person.FirstName, Pets = gj };

    foreach (var v in query)
    {
        // Output the owner's name.
        Console.WriteLine("{0}:", v.OwnerName);
        // Output each of the owner's pet's names.
        foreach (Pet pet in v.Pets)
            Console.WriteLine("  {0}", pet.Name);
    }
}

// This code produces the following output:
//
// Magnus:
//   Daisy
// Terry:
//   Barley
//   Boots
//   Blue Moon
// Charlotte:
//   Whiskers
// Arlene:

XML を作成するグループ化結合の例

グループ化結合は、LINQ to XML を使用して XML を作成するのに適しています。次の例は前の例に似ていますが、匿名型を作成するのではなく、結果セレクタ機能により、結合されたオブジェクトを表す XML 要素を作成する点が異なります。LINQ to XML の詳細については、「LINQ to XML」を参照してください。

class Person
{
    public string FirstName { get; set; }
    public string LastName { get; set; }
}

class Pet
{
    public string Name { get; set; }
    public Person Owner { get; set; }
}

/// <summary>
/// This example creates XML output from a grouped join.
/// </summary>
public static void GroupJoinXMLExample()
{
    Person magnus = new Person { FirstName = "Magnus", LastName = "Hedlund" };
    Person terry = new Person { FirstName = "Terry", LastName = "Adams" };
    Person charlotte = new Person { FirstName = "Charlotte", LastName = "Weiss" };
    Person arlene = new Person { FirstName = "Arlene", LastName = "Huff" };

    Pet barley = new Pet { Name = "Barley", Owner = terry };
    Pet boots = new Pet { Name = "Boots", Owner = terry };
    Pet whiskers = new Pet { Name = "Whiskers", Owner = charlotte };
    Pet bluemoon = new Pet { Name = "Blue Moon", Owner = terry };
    Pet daisy = new Pet { Name = "Daisy", Owner = magnus };

    // Create two lists.
    List<Person> people = new List<Person> { magnus, terry, charlotte, arlene };
    List<Pet> pets = new List<Pet> { barley, boots, whiskers, bluemoon, daisy };

    // Create XML to display the hierarchical organization of people and their pets.
    XElement ownersAndPets = new XElement("PetOwners",
        from person in people
        join pet in pets on person equals pet.Owner into gj
        select new XElement("Person",
            new XAttribute("FirstName", person.FirstName),
            new XAttribute("LastName", person.LastName),
            from subpet in gj
            select new XElement("Pet", subpet.Name)));

    Console.WriteLine(ownersAndPets);
}

// This code produces the following output:
//
// <PetOwners>
//   <Person FirstName="Magnus" LastName="Hedlund">
//     <Pet>Daisy</Pet>
//   </Person>
//   <Person FirstName="Terry" LastName="Adams">
//     <Pet>Barley</Pet>
//     <Pet>Boots</Pet>
//     <Pet>Blue Moon</Pet>
//   </Person>
//   <Person FirstName="Charlotte" LastName="Weiss">
//     <Pet>Whiskers</Pet>
//   </Person>
//   <Person FirstName="Arlene" LastName="Huff" />
// </PetOwners>

コードのコンパイル方法

  • Visual Studio で新しいコンソール アプリケーション プロジェクトを作成します。

  • System.Core.dll と System.Xml.Linq.dll がまだ参照されていない場合は、System.Core.dll と System.Xml.Linq.dll への参照を追加します。

  • System.Linq 名前空間と System.Xml.Linq 名前空間を含めます。

  • 例からコードをコピーし、program.cs ファイルの Main メソッドの下に貼り付けます。貼り付けたメソッドを呼び出すコード行を Main メソッドに追加します。

  • プログラムを実行します。

参照

処理手順

方法 : 内部結合を実行する (C# プログラミング ガイド)

方法 : 左外部結合を実行する (C# プログラミング ガイド)

概念

結合演算

匿名型

参照

Join

GroupJoin

匿名型 (C# プログラミング ガイド)

その他の技術情報

LINQ to XML