中の技術日誌
 ホーム / 上へ

技術解説 .NET 2.0 ジェネリック(Generics)  第3回 List<T>.FindAll(Predicate<T>)

2006/01/26

この文書はVisual Studio 2005をベースに記述されています。

第3回 List<T>.FindAll(Predicate<T>)

今回はFindAllをはじめとするFind系メソッドだ。

あるArrayListに入っているデータの文字列が、数字の場合に別のArrayListに構築する想定だ。

まずは従来型のソースを見てもらおう。

1.x C#
ArrayList al = new ArrayList();
al.Add("1");
al.Add("B");
al.Add("3");
ArrayList al2 = new ArrayList();
foreach( string text in al)
{
  try
  {
    int.Parse(text);
    al2.Add(text);
  }
  catch
  {
  }
}
1.x VB
Dim al As ArrayList = New ArrayList
al.Add("1")
al.Add("B")
al.Add("3")
Dim al2 As ArrayList = New ArrayList
For Each text As String In al
  Try
    Int32.Parse(text)
    al2.Add(text)
  Catch ex As Exception
  End Try
Next
1.x MC++
ArrayList __gc *al = new ArrayList();
al->Add(S"1");
al->Add(S"B");
al->Add(S"3");
ArrayList __gc *al2 = new ArrayList();
for ( int LoopCounter = 0; LoopCounter < al->Count; LoopCounter++ )
{
  try
  {
    Int32::Parse(static_cast<String*>(al->Item[LoopCounter]));
    al2->Add(static_cast<String*>(al->Item[LoopCounter]));
  }
  catch(Exception*)
  {
  }
}

従来のコーディングであれば、やはり一つ一つArrayListから取り出して評価していくことになる。

この場合取り出すべきデータなのか、そうでないのかというのは例外のキャッチで表現されているので、なんとなくわかるが、true/falseといった形で明確になっていない。

場合によってはExceptionで何か他の例外が発生するのでそれを捕まえるためかと思われてしまう。

2.0 C#
private void button1_Click(object sender, EventArgs e)
{
  List<string> ls = new List<string>();
  ls.Add("1");
  ls.Add("B");
  ls.Add("3");
  Predicate<string> numsel = new Predicate<string>(NumericSelector);
  List<string> ls2 = ls.FindAll(numsel);
}
public bool NumericSelector(string text)
{
  try
  {
    int.Parse(text);
    return true;
  }
  catch (FormatException)
  {
    return false;
  }
}
2.0 VB
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
  Dim ls As List(Of String) = New List(Of String)
  ls.Add("1")
  ls.Add("B")
  ls.Add("3")
  Dim numsel As Predicate(Of String) = New Predicate(Of String)(AddressOf NumericSelector)
  Dim ls2 As List(Of String) = ls.FindAll(numsel)
End Sub
Public Function NumericSelector(ByVal text As String) As Boolean
  Try
    Int32.Parse(text)
    Return True
  Catch ex As Exception
    Return False
  End Try
End Function
private:
System::Void button1_Click(System::Object^  sender, System::EventArgs^  e)
{
  List<String^>^ ls = gcnew List<String^>();
  ls->Add("1");
  ls->Add("B");
  ls->Add("3");
  Predicate<String^>^ numsel = gcnew Predicate<String^>(this, &Form1::NumericSelector);
  List<String^>^ ls2 = ls->FindAll(numsel);
}
public :
bool NumericSelector(String^ text)
{
  try
  {
    Int32::Parse(text);
    return true;
  }
  catch(Exception^)
  {
    return false;
  }
}

このように一部のデータを抜き出すということ(FindAll)にこのような処理を行うということがより明確になっていると思う。

このPredicateデリゲートは

delegate bool Predicate(<T>)

となっており、YesかNoかの判定に使われる。

List<T>の中で利用されているのは

.Exists
.Find
.FindAll
.FindIndex
.FindLast
.FindListIndex
.RemoveAll
.TrueForAll

と多用されている。

ちなみにArrayにも同様に採用されているので、単純な配列でも同様の処理が可能だ。

おまけの匿名メソッド版の場合には記述が離れた位置にならないため、よりわかりやすい記述になる。

2.0 C#(匿名メソッドを使った場合)
private void button1_Click(object sender, EventArgs e)
{
  List<string> ls = new List<string>();
  ls.Add("1");
  ls.Add("B");
  ls.Add("3");
  List<string> ls2 = ls.FindAll(delegate(string text)
  {
    try
    {
      int.Parse(text);
      return true;
    }
    catch (FormatException)
    {
      return false;
    }
  });
}

[戻る] [進む]


勉強会: 05/18 大阪 登録受付中

中の技術日誌
コンテンツ
わんくま同盟
わんくま同盟
わんくま同盟
広告
バナー
MVP LOGO
MSMVP Visual C# Since 2004/04-2007/03
MCP LOGO
070-316
姉妹サイト
姉妹サイト:じゃんぬのC#, VB.NET 入門
じゃんぬの
C#, VB.NET 入門
検索
Google

ブログ本家
広告