DOBON.NET DOBON.NETプログラミング掲示板過去ログ

多次元配列クラスの作成について

環境/言語:[WindowsXP、.NET Framework2.0]
分類:[.NET]

2009/06/13(Sat) 18:41:26 編集(投稿者)

はじめまして。
VB.Net学習中の初心者なのですが、多次元配列相当のクラス(もしくは構造体)を作れないかなといろいろ試していますが、経験/センスがないのでなかなか思うようなプログラムが作成できず困っています。
他掲示板にて聞いたやり方を元にサンプルクラスを作成したのですが、使いがってなど、これでよいのかと心配で。。。
ご意見、ご指摘を受けれればということで、こちらの掲示板にも書かせて頂くことにしました。m(_ _)m
すみませんが、お詳しい方がおられましたらご教示頂けますと幸いです。

◆配列でいうとAAA(N)がX個存在するような形をとりたく、
AAA(X1).N1
AAA(X1).N2
AAA(X1).N3
  :
AAA(X2).N1
AAA(X2).N2
AAA(X2).N3
  :
のように使用する方向で考えています。
N1〜N3..の型はそれぞれで宣言する形にしようと考えています。
(N1:Integer,N2:String,N3:DateTimeなど)

そこで出来た↓ですが、Containsメソッドが使用できない点や、インスタンスをIndex数分生成しなくてはいけないのがどぉなのかなと思っています。
何か良い方法をお解かりの方がおられましたら、よろしくお願い致します。

--------------------------------------------------------------------------
Public Class Array2

    Public Shared Sub test()
        Dim aryTest As New ArrayList
        Dim Man1 As New MemberNN(1, "N1", Today())
        Dim Man2 As New MemberNN(2, "N2", Today())
        Dim Man3 As New MemberNN(3, "N3", Today())
        Dim Man4 As New MemberNN(2, "N2", Today())
        Try
            aryTest.Add(Man1)       'Item(0)に{1,"N1",Today()}をAdd
            aryTest.Add(Man2)       'Item(1)に{2,"N2",Today()}をAdd

            'aryTestの中身をテスト出力
            Console.WriteLine(String.Format("aryTest.Count:{0}", _
              aryTest.Count))
            Console.WriteLine(String.Format("aryTest.Item(0):{0}{1}{2}{1}{3}", aryTest.Item(0).N1, ",", aryTest.Item(0).N2, aryTest.Item(0).N3))
            Console.WriteLine(String.Format("aryTest.Item(1):{0}{1}{2}{1}{3}", aryTest.Item(1).N1, ",", aryTest.Item(1).N2, aryTest.Item(1).N3))

            'Containsメソッド確認用テスト出力
            If aryTest.Contains(Man3) Then
                Console.WriteLine("MAN3はAddされておらずここは通らない")
            ElseIf aryTest.Contains(Man1) Then
                Console.WriteLine("MAN1は既にAdd済みのためここは通る")
            End If
            If aryTest.Contains(Man4) Then
                Console.WriteLine("N1〜N3の値はMan2=Man4だがAddしていないMan4はContainsで見つからずここは通らない")
                '⇒つまり、Containsメソッドは存在はするが意図した使用が不可能(T_T)
            End If

            'Clearメソッド確認
            aryTest.Clear()
            Console.WriteLine(String.Format("aryTest.Count:{0}", aryTest.Count))

        Catch ex As Exception
            Throw
        Finally
            'Newしただけに、DisposeかNothing入れとくべき!?
            '要素分処理記述はきついですね(T_T)
            Man1 = Nothing : Man2 = Nothing : Man3 = Nothing : Man4 = Nothing
        End Try
    End Sub
--------------------------------------------------------------------------
    Public Class MemberNN

        Private _n1 As Integer
        Private _n2 As String
        Private _n3 As Date
        Sub New(ByVal _nn1 As Integer, ByVal _nn2 As String, ByVal _nn3 As Date)
            _n1 = _nn1 : _n2 = _nn2 : _n3 = _nn3
        End Sub
        Public ReadOnly Property N1() As Integer
            Get
                Return _n1
            End Get
        End Property
        Public ReadOnly Property N2() As String
            Get
                Return _n2
            End Get
        End Property
        Public ReadOnly Property N3() As Date
            Get
                Return _n3
            End Get
        End Property
    End Class
End Class
--------------------------------------------------------------------------
==出力==
aryTest.Count:2
aryTest.Item(0):1,N1,2009/06/13 0:00:00
aryTest.Item(1):2,N2,2009/06/13 0:00:00
MAN1は既にAdd済みのためここは通る
aryTest.Count:0
--------------------------------------------------------------------------


■No24738に返信(すらりんさんの記事)
> 多次元配列相当のクラス
よく分からないけど使いたいようなクラスではないね。
クラスの2次元配列ではなぜダメなの?

Private Mans(10, 5) As MemberNN

Private Sub test
        For row As Integer = 0 To Mans.GetLength(0) - 1
            For col As Integer = 0 To Mans.GetLength(1) - 1
                Mans(row, col) = New MemberNN(row, "N" & col.ToString, Today())
            Next
        Next
End Sub

ArrayList の配列ではなぜダメなの?

Private aryTest(5) As ArrayList

> 他掲示板にて聞いたやり方を元に
なぜその掲示板で続けないの?今まで貴方が考えてきたことを
ボクは全く知らないわけです。一から聞き出さないといけないの?
せめてリンクくらい貼ったら?
るしぇさん、
返信ありがとうございます。

>>他掲示板にて聞いたやり方を元に
> なぜその掲示板で続けないの?今まで貴方が考えてきたことを
> ボクは全く知らないわけです。一から聞き出さないといけないの?
> せめてリンクくらい貼ったら?
⇒すみませんでした。あまり他掲示板のURLを貼り付けるとかはどうなのかなって思って控えていました。
色々な考え方や知識を持っておられる場合が多いので、こちらの掲示板にも投稿させていただいた次第です。

考え方としては、HashTableクラスを使用したいイメージです。
ただ、HashTableはKeyに対してValueが一つしかもてないですが、
今回考えているのはKeyに対してValue1,Value2,Value3みたいに型別の
メンバを持てて、且つAdd,Clear,Count,Containsメソッドなどが使えると便利かなと思っておりました。

値を取り出したいときもFor文等でまわす必要がありませんし、追加する場合もContainsで確認した上でAddってのが便利なので。
ただ、むずかしいですね。
■No24742に返信(すらりんさんの記事)
> 考え方としては、HashTableクラスを使用したいイメージです。
> ただ、HashTableはKeyに対してValueが一つしかもてないですが、
> 今回考えているのはKeyに対してValue1,Value2,Value3みたいに型別の
> メンバを持てて、且つAdd,Clear,Count,Containsメソッドなどが使えると便利かなと思っておりました。

自分の構造体やクラスを定義して、そのインスタンスをHashTableなり、Dictionary(Of TKey, Of TValue)なりのValueに突っ込めば良いのでは?
HashTableだと一度、その自分の構造体やクラスにキャストしないと駄目かもしれませんが…。


ArrayListなり、List(Of T)なりでやるのであれば、構造体でやると比較関数等を実装する手間が省けて楽かもしれませんね。
クラスでやるなら、Containsで同一であるという比較関数等を実装する必要があると思います。
(メンバーに参照型(クラス)があるなら、どのみち何か手を打つ必要があります)
イメージとしてはこんなところ。

Sub Main()
Dim hashTest As New Hashtable
Dim Man1 As New MemberNN(1, "N1", Today())

' キーを指定して追加
hashTest.Add(1, Man1)

' キーを指定して取り出し
Dim result As Integer = hashTest(1).N1
End Sub
2009/06/14(Sun) 10:40:39 編集(投稿者)

>Azuleanさん

どうもありがとうございますm(_ _)m
HashTableを使うやり方で意図した使い方ができるようになりました。
N1(Integer),N2(Date)とし、N2で使用していたString型をHashTableのKeyとして扱うやり方で作ってみました。
これまでN1〜N3のメンバのうち、1つをユニークとして扱う方法で考えていたので、String型の"NX"を当てはめてみました。
(Key=Integer型でもOKでしたが汎用的につかえそうなため実験してみました)
大変勉強になりました。ありがとうございます。

------------------------------------------------------------------------------------
Public Class Test
    Public Shared Sub test2()
        Dim hsTbl As New Hashtable
        Dim Man1 As New MemberNN(1, Today())    'Key="KEY1"とする
        Dim Man2 As New MemberNN(2, Today())    'Key="KEY2"とする
        Dim Man3 As New MemberNN(6, Today())    'Key="KEY3"とする
        Dim Man4 As New MemberNN(8, Today())    'Key="KEY4"とする
        Try
            hsTbl.Add("KEY1", Man1)               'hsTbl("KEY1")に{1,Today()}をAdd
            hsTbl.Add("KEY2", Man2)               'hsTbl("KEY2")に{2,Today()}をAdd

            Console.WriteLine(String.Format("hsTbl.Count:{0}", hsTbl.Count))
            Console.WriteLine(String.Format("hsTbl(""KEY1""):{1}N1={0}{1}N2={2}", hsTbl("KEY1").N1, ControlChars.CrLf, hsTbl("KEY1").N2))
            Console.WriteLine(String.Format("hsTbl(""KEY2""):{1}N1={0}{1}N2={2}", hsTbl("KEY2").N1, ControlChars.CrLf, hsTbl("KEY2").N2))

            'Containsメソッド使用で追加
            If Not hsTbl.Contains("KEY4") Then
                'KEY4は存在しないためここで追加
                hsTbl.Add("KEY4", Man4)           'hsTbl("KEY4")に{2,Today()}をAdd
                Console.WriteLine(String.Format("hsTbl(""KEY4""):{1}N1={0}{1}N2={2}", hsTbl("KEY4").N1, ControlChars.CrLf, hsTbl("KEY4").N2))
            End If

            'Containsメソッドテスト出力
            If hsTbl.Contains("KEY3") Then
                Console.WriteLine("MAN3はAddされておらずここは通らない")
            ElseIf hsTbl.Contains("KEY1") Then
                Console.WriteLine("MAN1は既にAdd済みのためここは通る")
            End If

            'Clearメソッド確認
            hsTbl.Clear()
            Console.WriteLine(String.Format("hsTbl.Count:{0}", hsTbl.Count))

        Catch ex As Exception
            Throw
        Finally
            If Not hsTbl Is Nothing Then hsTbl = Nothing
            Man1 = Nothing : Man2 = Nothing : Man3 = Nothing : Man4 = Nothing
        End Try
    End Sub
------------------------------------------------------------------------------------
    Public Class MemberNN
        Private _n1 As String
        Private _n2 As Date
        Sub New(ByVal _nn1 As String, ByVal _nn2 As Date)
            _n1 = _nn1 : _n2 = _nn2
        End Sub
        Public ReadOnly Property N1() As String
            Get
                Return _n1
            End Get
        End Property
        Public ReadOnly Property N2() As Date
            Get
                Return _n2
            End Get
        End Property
    End Class
End Class
------------------------------------------------------------------------------------
(出力)
hsTbl.Count:2
hsTbl("KEY1"):
N1=1
N2=2009/06/14 0:00:00
hsTbl("KEY2"):
N1=2
N2=2009/06/14 0:00:00
hsTbl("KEY4"):
N1=8
N2=2009/06/14 0:00:00
MAN1は既にAdd済みのためここは通る
hsTbl.Count:0
------------------------------------------------------------------------------------
...なんかグレーになって戻らなくなってしまった^^;
すみません。
解決済み!

DOBON.NET | プログラミング道 | プログラミング掲示板