中の技術日誌ブログ

C#とC++/CLIと
VBと.NETとWindowsで戯れる
 

目次

Blog 利用状況

ニュース

自己紹介

東京でソフトウェアエンジニアをやっています。
お仕事大募集中です。
記事執筆や、講師依頼とかでも何でもどうぞ(*^_^*)
似顔絵 MSMVPロゴ
MSMVP Visual C# Since 2004/04-2013/03

記事カテゴリ

書庫

日記カテゴリ

00-整理

01-MSMVP

第6回 IComparerとDictionary(IComparer)

第6回 IComparer<T>とDictionary(IComparer<T>)

.Net1.xの世界ではIComparerというインターフェイスはobjとobjを比較するもので、どうしてもキャストしないといけないものであった。

.Net2.0ではIComparer<T>というものが導入されることになる。

これを利用すると、Dictionary<K, V>のKeyに独自のクラスを設定したりする場合に非常に便利になる。

まず利用するクラスを下記のように定義する。

下記が実際のクラス定義

public class 商品Key
{
  public string 商品コード;
  public string カラー;
}
public class 商品
{
  public string 商品コード;
  public string カラー;
  public string 一般商品名;
  public decimal 希望小売価格;
  public 商品Key 商品Key
  {
    get
    {
      商品Key key = new 商品Key();
      key.商品コード = this.商品コード;
      key.カラー = this.カラー;
      return key;
    }
  }
}
public class 商品Comparer : IComparer<商品Key>
{
  public int Compare(商品Key x, 商品Key y)
  {
    int CompareInfo = x.商品コード.CompareTo(y.商品コード);
    if (CompareInfo != 0)
    {
      return CompareInfo;
    }
    else
    {
      CompareInfo = x.カラー.CompareTo(y.カラー);
      if (CompareInfo != 0)
      {
        return CompareInfo;
      }
      else
      {
        return 0;
      }
    }
  }
  public bool Equals(商品Key x, 商品Key y)
  {
    if (x.商品コード == y.商品コード && x.カラー == y.カラー)
    {
      return true;
    }
    else
    {
      return false;
    }
  }
  public int GetHashCode(商品Key obj)
  {
    string HashData = string.Format("商品コード:{0}\r\nカラー:{1}", obj.商品コード, obj.カラー);
    return HashData.GetHashCode();
  }
}
Public Class 商品Key
  Public 商品コード As String
  Public カラー As String
End Class
Public Class 商品
  Public 商品コード As String
  Public カラー As String
  Public 一般商品名 As String
  Public 希望小売価格 As Decimal
  Public ReadOnly Property 商品Key() As WindowsApplication1.商品Key
    Get
      Dim key As 商品Key = New 商品Key()
      key.商品コード = Me.商品コード
      key.カラー = Me.カラー
      Return key
    End Get
  End Property
End Class
Public Class 商品Comparer
  Implements IComparer(Of 商品Key)
  Public Function Compare(ByVal x As 商品Key, ByVal y As 商品Key) As Integer Implements System.Collections.Generic.IComparer(Of 商品Key).Compare
    Dim CompareInfo As Integer = x.商品コード.CompareTo(y.商品コード)
    If (CompareInfo <> 0) Then
      Compare = CompareInfo
      Exit Function
    Else
      CompareInfo = x.カラー.CompareTo(y.カラー)
      If (CompareInfo <> 0) Then
        Compare = CompareInfo
        Exit Function
      Else
        Return 0
      End If
    End If
  End Function
  Public Function Equals1(ByVal x As 商品Key, ByVal y As 商品Key) As Boolean Implements System.Collections.Generic.IComparer(Of 商品Key).Equals
    If (x.商品コード = y.商品コード And x.カラー = y.カラー) Then
      Equals1 = True
    Else
      Equals1 = False
    End If
  End Function
  Public Function GetHashCode1(ByVal obj As 商品Key) As Integer Implements System.Collections.Generic.IComparer(Of 商品Key).GetHashCode
    Dim HashData As String = String.Format("商品コード:{0}\r\nカラー:{1}", obj.商品コード, obj.カラー)
    GetHashCode1 = HashData.GetHashCode()
  End Function
End Class
public ref class 商品Key : public System::Object
{
public:
  String^ 商品コード;
  String^ カラー;
};
public ref class 商品 : public System::Object
{
public:
  String^ 商品コード;
  String^ カラー;
  String^ 一般商品名;
  Decimal^ 希望小売価格;
  商品Key^ get商品Key()
  {
    商品Key^ key = gcnew 商品Key();
    key->商品コード = this->商品コード;
    key->カラー = this->カラー;
    return key;
  }
};
public ref class 商品Comparer : System::Collections::Generic::IComparer<商品Key^>
{
public:
  int Compare(商品Key^ x, 商品Key^ y)
  {
    int CompareInfo = x->商品コード->CompareTo(y->商品コード);
    if (CompareInfo != 0)
    {
      return CompareInfo;
    }
    else
    {
      CompareInfo = x->カラー->CompareTo(y->カラー);
      if (CompareInfo != 0)
      {
        return CompareInfo;
      }
      else
      {
        return 0;
      }
    }
  }
  bool Equals(商品Key^ x, 商品Key^ y)
  {
    if (x->商品コード == y->商品コード && x->カラー == y->カラー)
    {
      return true;
    }
    else
    {
      return false;
    }
  }
  int GetHashCode(商品Key^ obj)
  {
    String^ HashData = String::Format(L"商品コード:{0}\r\nカラー:{1}", obj->商品コード, obj->カラー);
    return HashData->GetHashCode();
  }
};

商品というクラスのうちの一部が実際のキーで、そのキーが複合キーの場合で、Dictionaryに格納するなどという場合以前までは直感的なコードは組めなかった。(ので今回は1.xソースは割愛)

2.0においてはDictionaryのキー検索ルーチンをIComparer<T>でより柔軟に設計することができる。

これだけのコードを組むと以下のルーチンでDictionary<T>に格納したり抜き出したりということができるようになる。

Dictionary<商品Key, 商品> dic = new Dictionary<商品Key, 商品>(new 商品Comparer());
商品 syo = new 商品();
syo.商品コード = "ABC00001";
syo.カラー = "Red";
syo.一般商品名 = "ドラゴンクエツト";
syo.希望小売価格 = 5000;
dic.Add(syo.商品Key, syo);
商品Key 検索キー = new 商品Key();
検索キー.商品コード = "ABC00001";
検索キー.カラー = "Red";
商品 syo2 = dic[検索キー];
MessageBox.Show(syo2.一般商品名);
Dim dic As Dictionary(Of 商品Key, 商品) = New Dictionary(Of 商品Key, 商品)(New 商品Comparer())
Dim syo As 商品 = New 商品()
syo.商品コード = "ABC00001"
syo.カラー = "Red"
syo.一般商品名 = "ドラゴンクエツト"
syo.希望小売価格 = 5000
dic.Add(syo.商品Key, syo)
Dim 検索キー As 商品Key = New 商品Key()
検索キー.商品コード = "ABC00001"
検索キー.カラー = "Red"
Dim syo2 As 商品 = dic(検索キー)
MessageBox.Show(syo2.一般商品名)
Dictionary<商品Key^, 商品^>^ dic = gcnew Dictionary<商品Key^, 商品^>(gcnew 商品Comparer());
商品^ syo = gcnew 商品();
syo->商品コード = "ABC00001";
syo->カラー = "Red";
syo->一般商品名 = L"ドラゴンクエツト";
syo->希望小売価格 = gcnew Decimal(5000);
dic->Add(syo->get商品Key(), syo);
商品Key^ 検索キー = gcnew 商品Key();
検索キー->商品コード = "ABC00001";
検索キー->カラー = "Red";
商品^ syo2 = dic->Item[検索キー];
MessageBox::Show(syo2->一般商品名);

利用する側のソースは3言語ともほとんど同一だが、クラスのほうはなかなか特徴が出ていて面白いソースになった。

皆さんはどのソースがお好みだろう。

連載をまとめてあります。 http://blogs.users.gr.jp/naka/category/285.aspx

投稿日時 : 2004年12月12日 10:59

コメントを追加

# iqHqEyUUXnGFbI 2011/09/29 18:59 http://oemfinder.com

8p2b3o Every time I come back here again and don`t get disappointed..!

# IlzOIXMRCCUdQ 2011/10/06 0:16 http://www.cpc-software.com/products/Download-Adob

Fresh thoughts, fresh view on the subject..!

# RphZfvRTAJKJsLBT 2011/11/02 5:23 http://www.pharmaciecambier.com/

Well, actually, a lot of what you write is not quite true !... well, okay, it does not matter:D

# ceyJYwaFtpNJcl 2011/11/02 6:16 http://optclinic.com/

I decided to help and sent a post to the social bookmarks. I hope to raise it in popularity!!...

# ceyJYwaFtpNJcl 2011/11/02 6:16 http://optclinic.com/

I decided to help and sent a post to the social bookmarks. I hope to raise it in popularity!!...

# iwNfOnXkMfynuodQWT 2011/11/08 16:20 http://impuissancehomme.net

Hello! How do you feel about young composers?!...

# QcKSiqfCaJhD 2011/11/08 19:11 http://www.buylasix.biz

I decided to help and sent a post to the social bookmarks. I hope to raise it in popularity!!...

# cRnMwbQJwSmKPIRZ 2011/11/15 3:51 http://www.pharmaciedelange.com/

I do`t regret that spent a few of minutes for reading. Write more often, surely'll come to read something new!...

# QSJpnQKLqBsKzvbH 2011/11/16 3:33 http://www.goldcoffee.com/

Yeah, now it's clear !... And firstly I did not understand very much where there was the link with the title itself !!...

# epujFUncJbxgeqzCXQ 2011/11/16 3:53 http://www.laurenslinens.com/coldorbed.html

Heartfelt thanks..!

# QeorwqGPTEnCCNHt 2011/11/16 4:38 http://www.hooksandlattice.com/sidewalk-signs.html

It's straight to the point! You could not tell in other words! :D

タイトル
名前
URL
コメント