こんにちは。きわさです。
前回に引き続き、C#のLinqについてです。
今回はJoinです。
二つのリストから新しいリストを生成します。
例えば以下のようなユーザークラスと会社クラスがあり、
ユーザークラスのCompanyIdには、所属する会社(Company)のId入ります。
public class User
{
    public int Id { get; set; }
    public string Name { get; set; }
    public int CompanyId { get; set; }
}
public class  Company
{
    public int Id { get; set; }
    public string Name { get; set; }
    public DateTime Date { get; set; }
    public string Address { get; set; }
}
そして、以下のように全ユーザー、全会社のリストがそれぞれあるとします。
List<User> userList = new List<User>() 
{
    // 全ユーザーの情報   
}
List<Company> companyList = new List<Company>() 
{
    // 全会社の情報
}
そこで、あるユーザーの所属する会社名と住所を知りたくなりました。
Linqを使わずに書くと以下のようなループループな感じになりかねません。
var userId = 3; // 対象ユーザー
Company userCompany = null; 
foreach (var user in userList) 
{
    if (user.Id == userId)
    {
        foreach (var company in companyList)
        {
            if (user.CompanyId == company.Id)
            {
                userCompany = company;
                break;
            }
        }
        break;
    }    
}
前回のWhereを使ってみると次のように書くことができます。
var user = userList.Where(u => u.Id == userId).First(); var company = companyList.Where(c => c.Id == user.CompanyId).First();
.First()は1件目の要素を取得できます。
.Where(u => u.Id == userId).First()は直接
.First(u => u.Id == userId) と書くこともできます。
上記の場合のように、対象ユーザー一人分等であれば、よいかもしれませんが、
複数のユーザーの会社情報を一覧にしたい場合などではJoinが使えます。
var list = userList.Join(companyList,
                         u => u.CompanyId,
                         c => c.Id,
                         (u, c) => new 
                         { 
                             UserId = u.Id,
                             UserName = u.Name, 
                             CompanyName = c.Name,
                             CompanyAddress = c.Address, 
                         })
                   .ToList();
このようにすると、listは ユーザーID、氏名、会社名、会社住所をメンバにもつオブジェクトのリストとなります。
new { } の部分は 定義済みクラスで new XXX() { } のようにもできます。
あとは該当のユーザーの情報をとるなり、全ユーザーを一覧表示するなり、できます。
ループループしてなくてよいですね。
