wifrstfasnriov
@wifrstfasnriov (KA TO)

Are you sure you want to delete the question?

Leaving a resolved question undeleted may help others!

【VB.NET】定数クラスの作り方

解決したいこと

VisualStudioでWindowsフォームアプリを作っています。
VB.NETでの定数(数値のこともあれば文字のこともあり)の最も効率のよいまとめ方が知りたいです。

実現したい仕様

  1. 定数に別名をつけて管理
  2. 定数を分類して入れ子で管理
  3. 参照するときに入れ子に沿ってインテリセンスが効く
  4. どのクラスから参照するときでも毎回インスタンス化しなくていい
  5. 自分で定義した定数は1つのファイルにまとめる

イメージ

1ファイルに定数をまとめて書いておく

Class myConst
    Class Airport
        Const Haneda As String = "HND"
        Const Narita As String = "NRT"
    End Class
    Class Food
        Class Fruits
            '林檎でもりんごでもなくリンゴ
            Const Apple As String = "リンゴ"
        End Class
    End Class 
End Class

使うとき(ピリオド打つたびに候補が出てくる)

    aaa = myConst.Food.Fruits.Apple

試したことと頓挫した理由

  1. モジュールを使う
    1. インスタンス化せずに使えるが、入れ子のやり方がわからない
  2. 1つしかインスタンスができないクラスを作る
    1. 使うとき.Instance.を挟む必要がある
    2. 定数を定義するときが手間

定数まとめクラス

Public Class ClsConst
    Private Shared _instance As ClsConst
    Public Shared ReadOnly Property Instance() As ClsConst
        Get
            If _instance Is Nothing Then
                _instance = New ClsConst
            End If
            Return _instance
        End Get
    End Property
        Class Airport
        '内部クラス作るたびに Private Shared _instance as ~と書く必要がある
            Const Haneda  As String = "HND"
        End Class
    End Class
End Class

使うとき

aaa = ClsConst.Instance.Airport.Instance.Haneda

教えてください

使う言葉を一か所にまとめておくなんてどんなアプリ作るときでもやりたいことだと思われるのに、JavaはともかくVBやC#で同じことをやろうとしている例がネットで調べても全然出てきません。
おそらく自分で試したことの項は見当はずれのことやっているのであまり真面目に読んでいただく必要ありません。
実現したいのはイメージの項で書いたことなので、これに近いことを実現する方法に心当たりがあればご教示ください。
よろしくお願いいたします。

0

6Answer

@ozwk さん案の問題点

  • 階層によってキーワードを使い分けないといけない
  • 以下のような階層分けができない
Namespace myConst
    Namespace Food
        Module Fruits
            Const Apple As String = "リンゴ"
        End Module
        Const Rice As String = "こはん"  'ダメ
    End Namespace
End Namespace

@HalHarada さん案のはとてもオブジェクト指向的で「状況によって定数セットを切り替える」といった場合などには有用なんですが、これは定数セットというより「リードオンリーな値セットだけで構成されたクラス」と呼んだ方がいいものです。
(インスタンス経由でないとアクセスできないものは定数じゃない派なので)

@wifrstfasnriov さんが求めているのはクラスではなく「クラスのようにグループ化&階層化された定数セット」であり、クラスとして扱うことができる必要は特にないと受けとれました。

それなら @radian-jp さん案が一番「楽」だと思います。

Public Class myConst
    Public Class Food
        Public Class Fruits
            '林檎でもりんごでもなくリンゴ
            Public Const Apple As String = "リンゴ"
        End Class
        Public Const Rice As String = "こはん"  'OK
    End Class
End Class
3Like

VisualBasicに詳しくなくて恐縮ですが、コメント失礼いたします。
以下のページの「クラスを使い、入れ子になったモジュールと同等の宣言を行う例」が参考になるかもしれません。

モジュールはクラスとは異なり、入れ子にすることはできません。
モジュールは、ソースファイル内の最上位の要素として宣言するか、名前空間(Namespace)直下の要素として宣言する必要があります。

モジュールを入れ子にできない一方、どうしても入れ子になったモジュールが必要な場合は、代替手段としてクラスを用いることができます。

2Like

名前空間を使ってみました

VB.net
namespace myConst
    module Airport
        Const Haneda As String = "HND"
        Const Narita As String = "NRT"
    end module
    
    namespace Food
        module Fruits
            Const Apple As String = "リンゴ"
        end module
    end namespace
    
end namespace
2Like

最も効率が良い、というのは主観が入るので分かりませんが、
ConstやEnumであれば、Publicを付ければインスタンス化せずともアクセス出来るのではないかと。

Public Class myConst
    Public Class Airport
        Public Const Haneda As String = "HND"
        Public Const Narita As String = "NRT"
    End Class
    Public Class Food
        Public Class Fruits
            '林檎でもりんごでもなくリンゴ
            Public Const Apple As String = "リンゴ"
        End Class
    End Class
End Class

System.Drawing.Colorみたいな構造体値はConstに出来ないので、Shared ReadOnlyで代用せざるを得ないと思いますが。

    Public Class MyColor
        Public Shared ReadOnly Property ErrorText As Color = Color.Red
    End Class

定数多すぎてアクセス修飾子すら書きたくないとかなら、T4テンプレートやExcelで自動生成とかになりますかねぇ…(私はそこまで面倒だと思った事はないので、普通に書いてますが)

2Like

Comments

  1. > 暗黙のインスタンスというやつなのかな?と思いました。

    直接他の回答にコメント付ける事はできないのでこちらに書きますが、違います。
    定数、静的メンバーはインスタンスに属していません。

    https://learn.microsoft.com/ja-jp/dotnet/csharp/language-reference/keywords/static

    > 静的メンバーは、特定のオブジェクトではなく、型自体に属するメンバーです。

    > 定数の値は型のすべてのインスタンスで同じであるため、定数は静的フィールドのようにアクセスされます。
  2. あと、もし解決されているのであれば、質問のクローズをお願いします。

 常識に捕らわれ、私たちは地動説を唱える異端者を火刑にしました。しかし、革新的技術は異端者から起こるものです。
 見当はずれなことでも、有識者から常識はこれだから!常套手段はこれだから!と非難されても、トライすることをあきらめないでください。

さて、
 クラスは値と処理を1つの変数で管理するメリットがあり、インスタンス化は避けられません。(私の常識)


Public Class myConst
  Public Property Haneda As String 
    ・・・
Public Class ClsConst
    Inherits myConst
  ・・・
Module Program
    Sub Main(args As String())
        Dim obj = New ClsConst
  ・・・

 のように定数のみをメソッドクラスに継承することで、定数に奥行きを与えることができます。(Inheritsは多重継承が頭をよぎり、関数のincludeを応用したものかも?)

尚、通常のpublic定数でも同じ効果が得られます。

aaa = ClsConstInstanceAirportInstanceHaneda
しかし、
aaa = ClsConst.Instance.Airport.Instance.haneda
がメソッドチェーンなら別かもしれません。
(最後のHanedaがプロパティで、他はメソッド)

私の常識を覆す、新しい用法を期待します。

暇人x in 居酒屋

1Like

Comments

  1. @wifrstfasnriov

    Questioner

    ご報告が遅れました。一通り試しましたが、結論としては@albireoさんの仰る通りで、Public Classをただただ階層構造で作っていくのが一番私の需要にmatchしていました。使うときはどのオブジェクトを使うか明示せずに使っているようなものなもので、複雑な操作をする場合は何か問題が生じるだろうなと思いますが、今回のように定数保管庫にするだけならば問題なさそうです。
    暗黙のインスタンスというやつなのかな?と思いました。
    何はともあれ解決しました。
    みなさま、ありがとうございました。
    (参考1 https://social.msdn.microsoft.com/Forums/ja-JP/55781635-aaee-4f5b-85bb-29f3b4ce7c03/form1243421628124032098612377225802151212395new123993211823550123?forum=vbgeneralja
    (参考2 https://qiita.com/radian-jp/items/ef3aa3e008a6dcc13e49
  2. @wifrstfasnriov

    Questioner

    あれこれ参考2って @radian-jp さんの記事ですね(びっくり)

Your answer might help someone💌