SHOEISHA iD

※旧SEメンバーシップ会員の方は、同じ登録情報(メールアドレス&パスワード)でログインいただけます

DeveloperZine(デベロッパージン)- エンジニアの意思決定を支える技術情報メディア ProductZine

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

japan.internet.com翻訳記事

.NET データ処理に役立つ26のヒント(後編)

.NETにおけるデータ管理のテクニック

ヒント3:.NETのジェネリックによる並べ替え

 Listジェネリッククラスには、並べ替え処理と検索処理を行うためのメソッドがあります。また、独自の並べ替えや検索のロジックを実装することもできます。それぞれ見てみることにしましょう。

 次のコードは、選手名による並べ替えと、チームごとの選手名による並べ替えの例です。いずれも、「匿名メソッド」というC#の新しい言語機能を使用して、並べ替えのロジックをインラインで指定しています。

private void TestSortBaseballClass()
{
    List<BaseballClass> oBaseball = new List<BaseballClass>();
    oBaseball = this.PopulateBaseballClass();
    string cResults = "";
   
    // Anonymous delegate to sort on name
    oBaseball.Sort (delegate(BaseballClass f1, BaseballClass f2)
    {
        return f1.Name.CompareTo(f2.Name);
    }
   
    // Anonymous delegate to sort on Team, then Name
    oBaseball.Sort (delegate(BaseballClass f1, BaseballClass f2)
    {
        return f1.Name.Insert(0, f1.Team).CompareTo(
                                       f2.Name.Insert(0, f2.Team));
    }
}

 匿名メソッドを使用すると、コードブロックをデリゲートにカプセル化でき、通常ならメソッド名を指定する部分に、インラインでコードを記述できます。メソッドを別途作成する必要がないため、デリゲートをインスタンス化するときのコーディングの手間を減らすことができます。デリゲートの代わりにコードブロックを指定する方法は、メソッドを作成するのが無駄な手間に感じられる場合に有効です。

 匿名メソッドの構文は、最初は扱いづらいように思えるかもしれません。しかし次の例では、匿名メソッドを使うことによって、クラスを余分に追加する手間が省けます。

// In-line anonymous method that compares 2 
// incoming values
oBaseball.Sort(delegate(BaseballClass f1, BaseballClass f2) {
    return f1.Name.CompareTo(f2.Name);
});
   
// A second anonymous method, inserts team 
// in front of name, to sort on two columns 
oBaseball.Sort(delegate(BaseballClass f1, BaseballClass f2) {
    return f1.Name.Insert(0, f1.Team).CompareTo( 
                                        f2.Name.Insert(0, f2.Team));
});

ヒント4:.NETのジェネリックでの検索と匿名メソッド(オプション)

 .NETのListジェネリッククラスには、検索を実行するためのメソッドとして、FindFindAllFindLastがあります。次の例のように、独自の検索ロジックをインラインで実装する匿名メソッドを作成することもできますし、Find系メソッドのPredicate(ブール値関数)となるクラスを作成することもできます(リスト1とリスト2を参照)。

private void TestFindBaseballClass()
{
    List<BaseballClass> oBaseball = new List<BaseballClass>();
    oBaseball = this.PopulateBaseballClass();
    string cSearch = "Astros";
    BaseballClass oSingleFind =
        oBaseball.Find( delegate(BaseballClass f1) 
        {
            return f1.Team == cSearch;
        });
    MessageBox.Show("Single find is " + oSingleFind);
    string cResults = "";
    foreach (BaseballClass oRecord in
        oBaseball.FindAll( (delegate(BaseballClass f1) 
        {
            return f1.Team == cSearch;
        })))
        cResults += oRecord + "\r\n";
    MessageBox.Show("Multiple find is " + oSingleFind);
}

 上のコードでは、その前の例と同じ手法を使っています。つまり、oBaseballの中身を検索して条件に一致する最初のインスタンスを探すデリゲートをインラインメソッドで作成しています。仮にここで、完全一致ではなく部分文字列による検索を実装するとしたら、匿名メソッド内で別の文字列関数を使用することも可能です。

 ListクラスのFindAllメソッドについても、同様の方法で使用できます。インラインのデリゲートと匿名メソッドを指定し、受け取った各BaseballClassオブジェクトで検索文字列に一致するものをブール値で返しています。FindAllメソッドでは、ADO.NETのDataTableオブジェクトのようなフィルタ機能を実装できます。

string cSearch = "Astros";
   
// Perform a single search on the first hit
BaseballClass oSingleFind = oBaseball.Find(
    delegate(BaseballClass f1)
    { 
        return f1.Team == cSearch;
     });
   
// Perform a find all (almost like a filter)
string cResults = "";
foreach (BaseballClass oRecord in   
    oBaseball.FindAll((delegate(BaseballClass f1)
    { 
        return f1.Team == cSearch;
    })))
    cResults += oRecord + "\r\n";

 独立したクラスとして作成したい場合(あるいはVisual Studio 2005で匿名メソッドをサポートしていないVB.NETを使用している場合)ために、独立したFindクラスの例とその使用例をリスト1とリスト2に示しておきます。

リスト1 ブール型メソッドを含む検索クラス
using System;
using System.Collections.Generic;
using System.Text;
namespace GenericsDemo
{
    class FindBaseballClass
    {
        private string team;
        public FindBaseballClass(string team)
        {
            this.team = team;
        }
        // Implement specific search logic - return true or false
        public bool TeamFind(BaseballClass oBaseball)
        {
            return oBaseball.Team == team;
        }
    }
}
リスト2 検索クラスの使用例(匿名メソッドなし)
private void TestFindBaseballClass()
{
   List<BaseballClass> oBaseball = new List<BaseballClass>();
   oBaseball = this.PopulateBaseballClass();
   FindBaseballClass oFind = new FindBaseballClass("Astros"); 
   BaseballClass oSingleFind = oBaseball.Find(  
      new Predicate<BaseballClass>(oFind.TeamFind));
   MessageBox.Show("Single find is " + oSingleFind);
   string cResults = "";
   foreach (BaseballClass oRecord in oBaseball.FindAll(
      new Predicate<BaseballClass>(oFind.TeamFind)))
      cResults += oRecord + "\r\n";
   MessageBox.Show("Multiple find is " + oSingleFind);
}

ヒント5:Listクラスへの他オブジェクトの格納

 前述のとおり、新しいListクラスには、.NETのどんな型でも格納できます。リスト3は、特定のインターフェイスを実装するクラスを格納する例です。たとえば、複数のレポートクラスがあり、それらはすべてGenerateDocumentというメソッドを持つとします。次のような処理を行うことで、メインの制御ループ構造を作成できます。

  • GenerateDocumentという1つのメソッドを持つ、IDocumentというインターフェイスを定義します。
  • IDocumentを実装する複数のレポートドキュメントクラス(SimpleClass1SimpleClass2など)を作成します。
  • IDocumentインターフェイスを実装しているさまざまなクラスを格納するためのListオブジェクトのインスタンスを作成します。
  • List<SimpleInterface.IDocument> oList = 
        new List<SimpleInterface.IDocument>();
    
  • レポートドキュメントクラス(SimpleClass1など)のインスタンスを作成し、リストにインスタンスを追加します。
  • リストを反復処理し、GenerateDocumentメソッドを呼び出します。
  • foreach(SimpleInterface.IDocument oClass in oList)
        oClass.GenerateDocument();
    

 この例については、GE HealthcareのRob Haleに感謝します。Robは、Boston CodeCampで私が開催したC# 2.0セッションの参加者で、このコードのアイデアの発案者です。本当にありがとう、Rob!

リスト3 インターフェイスを実装するオブジェクトのコレクション
public class SimpleInterface
{
   public interface IDocument
   {
      void GenerateDocument ();
   }
}
class SimpleClass1 : SimpleInterface.IDocument
{
   public SimpleClass1() 
   { 
   }
   public void GenerateDocument()
   {
      // Method code goes here!
   }
}
class SimpleClass2 : SimpleInterface.IDocument
{
   public SimpleClass2() 
   { 
   }
   public void GenerateDocument()
   {
      // Method code goes here!
   }
}
List<SimpleInterface.IDocument> oList = 
   new List<SimpleInterface.IDocument>();
SimpleClass1 oClass1 = new SimpleClass1();
SimpleClass2 oClass2 = new SimpleClass2();
oList.Add(oClass1);
oList.Add(oClass2);
foreach (SimpleInterface.IDocument oClass in oList)
   oClass.GenerateDocument();

次のページ
ヒント6:Generics名前空間のその他のクラス

この記事は参考になりましたか?

japan.internet.com翻訳記事連載記事一覧

もっと読む

この記事の著者

japan.internet.com(ジャパンインターネットコム)

japan.internet.com は、1999年9月にオープンした、日本初のネットビジネス専門ニュースサイト。月間2億以上のページビューを誇る米国 Jupitermedia Corporation (Nasdaq: JUPM) のニュースサイト internet.comEarthWeb.com からの最新記事を日本語に翻訳して掲載するとともに、日本独自のネットビジネス関連記事やレポートを配信。

※プロフィールは、執筆時点、または直近の記事の寄稿時点での内容です

Kevin S. Goff(Kevin S. Goff)

.NET、Visual FoxPro、SQL Server、Crystal Reportsによる独自のWebソリューション/デスクトップソリューションを提供するコンサルティンググループ「Common Ground Solutions」の創業者兼主任コンサルタント。ソフトウェアアプリケーションの開発経...

※プロフィールは、執筆時点、または直近の記事の寄稿時点での内容です

この記事は参考になりましたか?

この記事をシェア

CodeZine(コードジン)
https://codezine.jp/article/detail/794 2006/12/22 00:00

イベント

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

新規会員登録無料のご案内

  • ・全ての過去記事が閲覧できます
  • ・会員限定メルマガを受信できます

メールバックナンバー