C# と VB.NET の質問掲示板

ASP.NET、C++/CLI、Java 何でもどうぞ

C# と VB.NET の入門サイト

構造体の入れ子

[トピック内 8 記事 (1 - 8 表示)]  << 0 >>

■83897 / inTopicNo.1)  構造体の入れ子
  
□投稿者/ Oboe2001 (1回)-(2017/04/21(Fri) 09:44:05)

分類:[VB.NET/VB2005 以降] 

VB2017で、構造体/クラスを「入れ子構造」で使おうとしています。

Module Module1
    '果物
    Public Class Cls_Fruit
        Public Apple(7) As Integer
        Public Orange(7) As Integer
    End Class
    '野菜
    Public Class Cls_Vegitable
        Public Cabbage(7) As Integer
        Public Carrot(7) As Integer
    End Class
    '食材
    Public Class Cls_Food
        Public Fruit(1) As New Cls_Fruit
        Public Vegitable(1) As New Cls_Vegitable
    End Class
    'クラスを使って変数を宣言
    Public Food As New Cls_Food
End Module

VB6までは、Typeで宣言すれば入れ子構造を作ることができました。VB.NET以降では
TypeではなくStructureやClassを使えば良さそうだ、ということまでは分かりました。

しかしながら、「食材」のところで、「BC30053 配列を'New'で宣言することはできま
せん」と怒られてしまいます。

Food.Fruit(1).Apple(7) = 100 ……のような使い方をしたいのですが、どのように
宣言すれば良いのでしょうか。

引用返信 編集キー/
■83898 / inTopicNo.2)  Re[1]: 構造体の入れ子
□投稿者/ 魔界の仮面弁士 (1265回)-(2017/04/21(Fri) 10:21:16)
2017/04/21(Fri) 10:26:25 編集(投稿者)

No83897 (Oboe2001 さん) に返信
> VB6までは、Typeで宣言すれば入れ子構造を作ることができました。VB.NET以降では
> TypeではなくStructureやClassを使えば良さそうだ、ということまでは分かりました。

VB4〜VB6 でも、クラスの入れ子はできますね。
Class ステートメントではなく、*.cls ファイルでの宣言になりますが。


> しかしながら、「食材」のところで、「BC30053 配列を'New'で宣言することはできま
> せん」と怒られてしまいます。

要素数を指定して宣言すれば、それだけで配列のインスタンスが生成されますので、
New を使う必要が無いという事です。下記の 4 つはいずれも同じ意味です。


★案1★
Public Class Cls_Food
 Public Fruit(1) As Cls_Fruit
 Public Vegitable(1) As Cls_Vegitable
End Class


★案2★
Public Class Cls_Food
 Public Fruit() As Cls_Fruit
 Public Vegitable() As Cls_Vegitable
 Public Sub New()
  ReDim Fruit(1), Vegitable(1)
 End Sub
End Class

★案3★
Public Class Cls_Food
 Public Fruit() As Cls_Fruit = New Cls_Fruit() {Nothing, Nothing}
 Public Vegitable() As Cls_Vegitable = New Cls_Vegitable() {Nothing, Nothing}
End Class

★案4★
Public Class Cls_Food
 Public Fruit() As Cls_Fruit = New Cls_Fruit(1) {}
 Public Vegitable() As Cls_Vegitable = New Cls_Vegitable(1) {}
End Class


> Food.Fruit(1).Apple(7) = 100 ……のような使い方をしたいのですが、
Cls_Fruit が、VB.NET の「構造体(Strucutre)」や VB6 の「ユーザー定義型(Type)」ではなく、
Cls_Fruit が、VB.NET の「クラス(Class)」や VB6 の「クラス」として宣言されていた場合、
単に配列を確保しただけでは、個々の要素の初期値は Nothing になっています。

ですからクラスの配列であった場合には、VB6 でいうところの
 ReDim Food.Fruit(1)
 Set Food.Fruit(0) = New Cls_Fruit
 Set Food.Fruit(1) = New Cls_Fruit
のような処理が事前に必要です。


配列要素の初期化も併せて行うならこんな感じ。
今回は 0 To 1 な 2 要素な配列だけなので、直接書いてみます。

★案5★
Public Class Cls_Food
 Public Fruit() As Cls_Fruit = {New Cls_Fruit(), New Cls_Fruit()}
 Public Vegitable() As Cls_Vegitable = {New Cls_Vegitable(), New Cls_Vegitable()}
End Class

配列の要素数が多い場合は、初期化処理をコンストラクタ内で
ループ生成した方が良いでしょう。
引用返信 編集キー/
■83903 / inTopicNo.3)  Re[1]: 構造体の入れ子
□投稿者/ 大谷刑部 (24回)-(2017/04/21(Fri) 11:32:45)
No83897 (Oboe2001 さん) に返信
> VB2017で、構造体/クラスを「入れ子構造」で使おうとしています。
>
> Module Module1
> '果物
> Public Class Cls_Fruit
> Public Apple(7) As Integer
> Public Orange(7) As Integer
> End Class
> '野菜
> Public Class Cls_Vegitable
> Public Cabbage(7) As Integer
> Public Carrot(7) As Integer
> End Class
> '食材
> Public Class Cls_Food
> Public Fruit(1) As New Cls_Fruit
> Public Vegitable(1) As New Cls_Vegitable
> End Class
> 'クラスを使って変数を宣言
> Public Food As New Cls_Food
> End Module
>
> VB6までは、Typeで宣言すれば入れ子構造を作ることができました。VB.NET以降では
> TypeではなくStructureやClassを使えば良さそうだ、ということまでは分かりました。

上記でやりたいことであれば構造体で十分な気がしますが、
Classを使いたい理由は何でしょう?
VB6でTypeで使っていた変数を移植したいだけなら、
構造体を使った方が明らかに簡単だと思います。

今後、プロパティーやメソッドの機能を増やしたいなら、当然クラスという選択肢になりますが、
何でもかんでもクラスにする必要はないと思います。



引用返信 編集キー/
■83905 / inTopicNo.4)  Re[2]: 構造体の入れ子
□投稿者/ Hongliang (530回)-(2017/04/21(Fri) 11:48:31)
> 上記でやりたいことであれば構造体で十分な気がしますが、
> Classを使いたい理由は何でしょう?

> 何でもかんでもクラスにする必要はないと思います。

個人的には逆で、「Classで十分」であり、「Structureを使いたい理由」を考えるようにしています。
VB6は触ったことがないので、Typeとの互換性という文脈では何も言えませんが…。
引用返信 編集キー/
■83907 / inTopicNo.5)  Re[3]: 構造体の入れ子
□投稿者/ Oboe2001 (2回)-(2017/04/21(Fri) 13:04:17)
No83898 (魔界の仮面弁士さん) に返信

 インスタンスの生成や、Newを使った配列要素の初期化の方法について、大変参考になりました。無事プログラムが動作を初め大変感謝しています。
 
No83903 (大谷刑部さん) に返信

 最初は構造体でプログラムを作り始めたのですが、宣言の中で要素の数を記述するとエラーになってしまったので、クラスに書き直した次第です。

No83905 (Hongliang さん) に返信

 構造体とクラスのどちらを選択するべきかについて、私は勉強不足であると痛感しました。あまりにもVB6を使っていた期間が長すぎたのだと思います。

 皆様ありがとうございます。
解決済み
引用返信 編集キー/
■83909 / inTopicNo.6)  Re[4]: 構造体の入れ子
□投稿者/ 魔界の仮面弁士 (1268回)-(2017/04/21(Fri) 13:22:19)
No83907 (Oboe2001 さん) に返信
> 構造体とクラスのどちらを選択するべきかについて、私は勉強不足であると痛感しました。

VB6 当時の記述が、そもそも適切であったのかとか
VB.NET へ移行時に「直訳」で良いのかとか
出来る限り元のコードを維持するべきかどうかとか
いろいろな考え方があるとは思いますが
ひとまず参考資料として:

https://msdn.microsoft.com/ja-jp/library/ms229017%28vs.100%29.aspx
http://dobon.net/vb/dotnet/beginner/whenusestruct.html
解決済み
引用返信 編集キー/
■83912 / inTopicNo.7)  Re[4]: 構造体の入れ子
□投稿者/ 大谷刑部 (25回)-(2017/04/21(Fri) 18:27:53)
No83907 (Oboe2001 さん) に返信
>  構造体とクラスのどちらを選択するべきかについて、私は勉強不足であると痛感しました。あまりにもVB6を使っていた期間が長すぎたのだと思います。

VB6が長すぎたとかはあんまり関係ないと思います。

http://dobon.net/vb/dotnet/beginner/whenusestruct.html

にも、配列変数として使用する場合は構造体のメリットが大きいと記載されています。

>参照型の配列の場合、要素のインスタンスはメモリにバラバラに置かれます。一方値型の配列は、要素のインスタンスが一塊で(インラインで)メモリに置かれます。そのため、構造体の配列の方が要素の読み込みと書き込みの効率がよく、さらにガベージコレクションの負担が少ないです。

実際一般論としてVB6のTypeを使っているケースも
大半がこれに該当すると思います。
プロパティーもメソッドも存在するケースは、
クラスの方が圧倒的にいいと思いますが、

VB6のTypeの後継が構造体であることを考慮すると、
VB6でTypeで宣言されているのが最適だったものは、構造体に置き換える方がいい場合が多い
というだけです。

もっとも配列 + 構造体の代わりに
クラス + コレクションを使っているケースもあり、
VB6の時代からインデックス→名称取出とかができるので、
(配列 + 構造体ならループになる)
クラス + コレクションを推奨している人もおり、
そのどちらかがいいとなるとわかりません。

なので、元のロジックがVB6で配列 + 構造体で適当だったかどうかの検証は
必要と思います。



解決済み
引用返信 編集キー/
■83922 / inTopicNo.8)  Re[1]: 構造体の入れ子
□投稿者/ Jitta (291回)-(2017/04/24(Mon) 19:35:26)
No83897 (Oboe2001 さん) に返信
> VB2017で、構造体/クラスを「入れ子構造」で使おうとしています。
> 
> Module Module1
>     '果物
>     Public Class Cls_Fruit
>         Public Apple(7) As Integer
>         Public Orange(7) As Integer
>     End Class
>     '野菜
>     Public Class Cls_Vegitable
>         Public Cabbage(7) As Integer
>         Public Carrot(7) As Integer
>     End Class
>     '食材
>     Public Class Cls_Food
>         Public Fruit(1) As New Cls_Fruit
>         Public Vegitable(1) As New Cls_Vegitable
>     End Class
>     'クラスを使って変数を宣言
>     Public Food As New Cls_Food
> End Module
> 
> Food.Fruit(1).Apple(7) = 100 ……のような使い方をしたいのですが、どのように

気になる。
AppleとOrangeがともに7なのは何故?
偶然、それとも必然?
えーっと、構造体のメンバーは全て同じ大きさの配列なのか?ってこと。
ここにあるのは皆同じになっている。
だったら、メンバーを配列にするのではなく、
構造体の実態を配列にする方が扱いやすいのでは?

解決済み
引用返信 編集キー/

このトピックをツリーで一括表示


トピック内ページ移動 / << 0 >>

このトピックに書きこむ