ArrayList について への返答

投稿で使用できる特殊コードの説明。(別タブで開きます。)
本名は入力しないようにしましょう。
投稿した後で削除するときに使うパスワードです。返答があった後は削除できません。
返答する人が目安にします。相手が小学生か社会人かで返答の仕方も変わります。
最初の投稿が質問の場合、質問者が解決時にチェックしてください。(以降も追加書き込み・返信は可能です。)
※「過去ログ」について書くときはその過去ログのURLも書いてください。

以下の返答は逆順(新しい順)に並んでいます。

投稿者 葉月  () 投稿日時 2008/7/18 02:49:00
'Houserクラス 
Public Class Houser 
 
    Dim fields As Hashtable = New Hashtable 'filds 
    Dim id As String = String.Empty 'fildsのid要素 
    Dim name As String = String.Empty 'fildsのname要素 
    Dim group As String = String.Empty 'fildsのgroup要素 
    Dim count As Integer = 0 '各要素が参照するカウント 
 
    ''' <summary> 
    ''' fieldsからidを取得 
    ''' </summary> 
    Public Property idHouse() 
        Get 
            Return fields.Item(id) 
        End Get 
        Set(ByVal value) 
            id = "id" + count.ToString 
            fields.Add(id, value) 
        End Set 
    End Property 
 
    ''' <summary> 
    ''' fieldsからnameを取得 
    ''' </summary> 
    Public Property nameHouse() 
        Get 
            Return fields.Item(name) 
        End Get 
        Set(ByVal value) 
            name = "name" + count.ToString 
            fields.Add(name, value) 
        End Set 
    End Property 
 
 
    ''' <summary> 
    ''' fieldsからgourpを取得 
    ''' </summary> 
    Public Property groupHouse() 
        Get 
            Return fields.Item(group) 
        End Get 
        Set(ByVal value) 
            group = "group" + count.ToString 
            fields.Add(group, value) 
        End Set 
    End Property 
 
 
    ''' <summary> 
    ''' countを変更する。 
    ''' </summary> 
    Public Sub Counting(ByVal a As Integer) 
        count = a 
    End Sub 
 
 
    ''' <summary> 
    ''' fieldsの全要素を抜き出す。 
    ''' </summary> 
    Public Sub allCounting() 
 
        Console.WriteLine("") 
        Console.WriteLine("値の列挙") 
 
        '値項目の列挙 
        For Each i As String In fields.Values 
            Console.WriteLine(i) 
        Next 
 
        Console.WriteLine("エントリーの列挙") 
 
        'エントリーの列挙 
        For Each j As DictionaryEntry In fields 
            Console.WriteLine("{0} : {1}", j.Key, j.Value) 
        Next 
 
    End Sub 
 
End Class
投稿者 葉月  () 投稿日時 2008/7/18 02:48:00
サンプルコードは、FormとHouserでクラスが分かれています。 
文字数の関係で、クラスを一つずつ紹介します。 
 
'Form 
Public Class Form1 
 
    Dim instHouse As New Houser() 
 
    Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load 
        instHouse.idHouse = "000001" 
        instHouse.nameHouse = "Yamada" 
        instHouse.groupHouse = "A" 
        instHouse.Counting(1) 
 
        instHouse.idHouse = "000002" 
        instHouse.nameHouse = "Tanaka" 
        instHouse.groupHouse = "B" 
 
    End Sub 
 
 
    ''' <summary> 
    ''' IDを取得するボタン 
    ''' </summary> 
    Private Sub btnID_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnID.Click 
        Console.WriteLine(instHouse.idHouse) 
    End Sub 
 
 
    ''' <summary> 
    ''' Nameを取得するボタン 
    ''' </summary> 
    Private Sub btnName_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnName.Click 
        Console.WriteLine(instHouse.nameHouse) 
    End Sub 
 
 
    ''' <summary> 
    ''' Groupを取得するボタン 
    ''' </summary> 
    Private Sub btnGroup_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnGroup.Click 
        Console.WriteLine(instHouse.groupHouse) 
    End Sub 
 
 
    ''' <summary> 
    ''' 全要素を取得するボタン 
    ''' </summary> 
    Private Sub btnAll_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnAll.Click 
        instHouse.allCounting() 
    End Sub 
 
End Class
投稿者 葉月  () 投稿日時 2008/7/18 02:43:00
皆さんのやり取りで、HashTableの概要がわかりました。 
今までArrayList系のクラスしか使ったことがなかったので勉強になりました。 
ありがとうございます。 
 
今回はHashtableを用いてfieldsに全ての要素を格納してましたが、Listクラスのジェネリックでやった方が楽かも知れません。 
fieldsに全ての要素を入れるのではなく、id、name、groupの三つに分ける方法です。 
ジェネリック型の説明は下記を参考にしてください。 
 
Hashtableの説明について、@itのページがあったので紹介します。 
それから、私が動きを把握するために作ったサンプルコードを掲載します。 
初心者が作ったサンプルコードですので、全くお役に立たないかも知れませんが…… 
よかったら参考にしてください。 
 
>>>ジェネリック 
ArrayListは、型に関係なく格納することができます。 
しかし、場合によっては型に関係なく全てを格納できてしまうと、本来intで格納しておきたい情報を間違えてstring型まで格納してしまってもエラーになりません。 
それを、指定した型以外が格納した時点でコンパイルエラーにしてくれるのがジェネリックになります。 
ジェネリック型は、クラスを指定して格納することもできて便利です。 
.NET系ではlistで指定しますが、javaではarraylistにジェネリックを指定するだけです。 
厳密にはlistとArraylistは違いますが、似ていますので同じように使うことができます。 
 
>>>参考ページ 
ttp://www.atmarkit.co.jp/fdotnet/dotnettips/125hashtable/hashtable.html 
※ 先頭のhを省略しています。
投稿者 みどり  () 投稿日時 2008/7/18 01:37:00
みどりです。 
 
さきほどのコメントの波線の位置がズレてしまいました。 
波線は Record(1) の下です。 
 
ごめんなさい。
投稿者 みどり  () 投稿日時 2008/7/18 01:35:00
るしぇさん。すみません。 
 
何度か試した結果、上手くいきました。 
原因は私のミスでした。 
よねKENさんがアドバイスしてくれたものをコピー&ペーストでプログラム上に貼り付けた時点で 
        name = DirectCast(DirectCast(Record(1), Hashtable).Value("Name"), String)  
                                     ~~~~~~~~~ 
        型 'Char' の値を 'System.Collections.Hashtable' に変換できません。 
と表示され。Value を Item に変更しましたが、やはりエラーは取れませんでした。 
 
訳もよく分からないくせに Hashtable の箇所を ArrayList に変えてみたり、オブジェクトのメンバ一覧 
で表示されるものを順に試して見ましたがダメでした。 
(本当はこの時点で表示されているエラーメッセージを連絡すれば良かったのでしょうが...) 
 
るしぇさんからの注意を受けて、よくプログラムを調べてみるとエラーの 
箇所(Record(1))の Record がプログラムのなかで String 型で定義されており、 
目的の ArrayList 型 の Records とは別物であったことが分かりました。 
 
この Records の間違えに気付く前に System.Collections.Generic... を紹介して頂いたので 
そちらに気がそれてしまい、折角教えて頂いたのに深く調べて見ることを怠ってしまいました。 
 
短いプログラムにもかかわらずコピー&ペーストで楽をしようと考えたのも誤りですし。 
試験用のプロジェクトを別途作らず、作成中のプロジェクトで試したのも間違えでした。 
以後、気を付けます。 
 
よねKENさん、るしぇさん。すみませんでした。 
 
また、自分の勝手な都合で関連があると判断し別の問題提起を同じスレッド内で行ってしまい 
話の流れを乱してしまったことを深くお詫びします。
投稿者 るしぇ  () 投稿日時 2008/7/18 00:36:00
>>5 
>入力中に表示されるオブジェクトのメンバ一覧(?)を入力してみましたが上手くいきませんでした。 
いいえ、Item プロパティで上手くいくはずです。 
VB2008のヘルプでも特に問題になりそうな記述はありません。 
 
>たしかよねKENさんがおっしゃられているようなエラーだったと思います。  
上手くいかない場合はエラーメッセージが変わっていたと思います。 
エラーメッセージにはエラーの原因が書かれています。 
曖昧な表現ではなく、正確に報告してください。 
 
最初の質問が解決してないわけですし、新しい質問を同じ 
スレッドですると話の流れが見えなくなります。お止めください。
投稿者 みどり  () 投稿日時 2008/7/17 23:09:00
皆さんアドバス有難う御座います。(お礼が遅くなってすみません) 
 
> Record(1).Value("Name") で "Tanaka" が取得できるようにしたいのですが  
>↑  
>これではエラーになります。  
 
は、こんな感じで取得できたらなぁ~っていうイメージです。(説明不足でした) 
 
入力中に表示されるオブジェクトのメンバ一覧(?)を入力してみましたが上手くいきませんでした。 
たしかよねKENさんがおっしゃられているようなエラーだったと思います。 
使っているVBのバージョンはVB2008なので 
System.Collections.Generic.List 
System.Collections.Generic.Dictionary 
で試みようとヘルプを調べましたがジェネリック○○という難解な記述に出くわし今のところ断念 
しています。 
分かりやすい記述があるHP等があれば教えて下さい。 
 
あれこれと思考錯誤している時に新たな疑問に出くわしました。 
Hashtable は Object 型の要素を格納できるとあるので 
Public Structure stS 
  Dim x As Integer 
  Dim y As String 
End Structure stS 
Public S As stS 
Public H As New Hashtable 
S.x = 1      (※1) 
S.y = "one" 
H.Add("Ichi", S) 
S.x = 2      (※2) 
S.y = "Two" 
H.Add("Ni", S) 
としたところ 
Directcast(H("Ichi"),stS).x で 1 
Directcast(H("Ichi"),stS).y で "one" 
Directcast(H("Ni"),stS).x で 2 
Directcast(H("Ni"),stS).y で "two" 
が取得できました。 
 
この場合(※2)で(※1)の結果が上書きされていますが Hashtable には正しく格納されて 
いるところみると、構造体 S がコピーされて Hashtable 内に格納されているのでしょうか?
投稿者 よねKEN  () 投稿日時 2008/7/16 09:43:00
>>3 
> あの。えと。。Hashtable に Value プロパティは存在しないようですが?  
 
 
確かに。おそらく意図することを実現しようとしたらItemプロパティですね。 
HashtableについてMSDNでよく確認せずに回答していました。
投稿者 るしぇ  () 投稿日時 2008/7/16 02:50:00
>>2 
>Record(1).Value("Name") で "Tanaka" が取得できるようにしたいのですが  
>↑  
>これではエラーになります。  
あの。えと。。Hashtable に Value プロパティは存在しないようですが? 
[Hashtable メンバ] 
http://msdn.microsoft.com/ja-jp/library/system.collections.hashtable_members(VS.80).aspx 
 
Values だと ICollection を返します。 
目的の操作は Item では???
投稿者 よねKEN  () 投稿日時 2008/7/16 02:37:00
> Record(1).Value("Name") で "Tanaka" が取得できるようにしたいのですが  
>↑  
>これではエラーになります。  
 
なんというエラーになりましたか? 
たぶん、Record(1)が返す型はObjectなのにValueを 
そのまま呼ぼうとして、そんなメソッドないよ、と怒られているのでは? 
(Option Strict Onを指定している場合) 
正しくは以下のようにキャストが必要だと思います。 
 
Dim name As String 
name = DirectCast(DirectCast(Record(1), Hashtable).Value("Name"), String) 
 
ところで、VBのバージョンは何ですか?VB2005以降であれば、 
ArrayListの代わりにSystem.Collections.Generic.Listを 
Hashtableの代わりにSystem.Collections.Generic.Dictionary 
を使うと一々キャストしなくて済みます。
投稿者 みどり  () 投稿日時 2008/7/16 01:13:00
全て表示