プログラムが使用する定数のグループを格納する最良の方法は何ですか?[閉まっている]


97

私のプログラムが使用するさまざまな定数があります... strings、ints、doublesなど...それらを格納する最良の方法は何ですか?Enumデータがすべて同じタイプではないため、が必要だとは思わない。手動で各値を設定したい。すべてを空のクラスに保存するだけですか?それとももっと良い方法がありますか?


18
あなたがそれを望む方法-それはあなたがそれを必要とする方法です。
San Jacinto

回答:


135

おそらく、静的な読み取り専用プロパティを持つ静的クラスにそれらを置くことができます。

public static class Routes
{
    public static string SignUp => "signup";
}

23
+1ですが、ローカリゼーションのためにリソースファイルからこれらをプルできる場合はさらに優れています。
Joel Coehoorn、2009年

17
少し冗長なようです-なぜ静的な読み取り専用文字列ではないのですか?
emptyset

6
なぜ読み取り専用でconstではないのですか?実行時に値を設定しないので、それらを読み取り専用にする必要はありません。
フィリップウォレス

91
constの問題は、constに対してコンパイルされたアセンブリは、それら自体がコンパイルされたときにそれらのconstのローカルコピーを取得することです。したがって、値を変更する場合は、定数を定義しているアセンブリに依存するすべてのアセンブリも再コンパイルする必要があります。そのため、読み取り専用ルートを使用する方が安全な場合がよくあります。静的なパブリック値の代わりにプロパティを使用すると、インターフェイスを定数値に変更せずに、必要に応じて(ローカリゼーションから読み取るなど)将来的にプログラミングロジックを追加できます。
cfeduke、2009年

11
悪魔の支持者として、私はconstの利点がスイッチケースで使用できることを指摘しなければなりません。
arviman 2013

27

定数でいっぱいのクラスを使用するIMOは、定数には問題ありません。それらが時々変更される場合は、代わりに設定でAppSettingsを使用し、ConfigurationManagerクラスを使用することをお勧めします。

実際にAppSettingsまたは類似のものからプルされた「定数」がある場合でも、構成マネージャーからの読み取りをラップする「定数」クラスは常にあります。上記の設定値を使用したい場所にConstants.SomeModule.Setting直接頼る必要はなく、常により重要ConfigurationManager.AppSettings["SomeModule/Setting"]です。

このセットアップのボーナスポイントはSomeModule、定数ファイル内のネストされたクラスになる可能性が高いため、依存関係注入を使用して、依存SomeModuleするクラスに直接注入することも簡単にできます。また、インターフェイスを上に抽出して、使用するコードに依存関係をSomeModule作成することもできISomeModuleConfigurationます。これにより、依存関係を定数ファイルに分離でき、特にこれらの設定がAppSettingsおよび設定は環境固有であるため、構成変換を使用して変更します。


1
これに追加するだけです。理由は、ビルドするときに、他のアセンブリから使用される定数が更新されないためです。つまり、AssemblyAとAssemblyBがあり、BがAの定数を使用している場合、値は参照されずにコピーされるため、Aを再構築してもBは更新されません。これにより、奇妙なバグが発生する可能性があります。
Camilo Martin

1
@CamiloMartinそれを処理する多くの方法、あなたの「定数」はそれを避けるために静的な読み取り専用にすることができます、または私が言ったように、それらがブルームーンで複数回変更してConfigurationManagerを使用する場合。
Chris Marisic 2012年

はい、私が言ったのは、静的な読み取り専用を使用するのは慣例だからというだけではなく、実際に混乱の元になる可能性があるためです。また、ConfigurationManagerの代わりにリソースファイルがあります。名前に言語コードを含む別のリソースファイルを追加するだけで、コードが即座にローカライズされます。
カミロマーティン

問題は、このアセンブリを他のアセンブリから参照する場合、値をそれらの構成ファイルにコピーする必要があるということです
symbiont

@symbiontサードパーティコンポーネントとして共有可能にするために、必要に応じて、構成ファイルを埋め込み、マニフェストから読み取ることができます
Chris Marisic

19

私がやりたいことは次のとおりです(ただし、適切なタイプの定数を使用するには、最後まで読んでください)。

internal static class ColumnKeys
{
    internal const string Date = "Date";
    internal const string Value = "Value";
    ...
}

これ読んで、なぜconstあなたが望むものではないのかを知ってください。可能な定数のタイプは次のとおりです。

  • const田畑。他のアセンブリではコンパイル時に値がハードコードされるため、将来的に値変更される可能性がある場合は、アセンブリ間で使用しないでください(publicまたはprotected)。値を変更すると、再コンパイルされるまで、古い値が他のアセンブリによって使用されます。
  • static readonly 田畑
  • static なしのプロパティ set

1
複数のアセンブリで使用すると読み取り専用になるのはなぜですか?
フィリップウォレス

静的readonlyが複数のアセンブリでconstよりもうまく機能するのはなぜですか?
マシュー

15
const値は、ソースアセンブリからコンパイル済みコードにコピーされます。つまり、const値を変更する必要がある場合は、すべての依存アセンブリを新しいバージョンに対して再コンパイルする必要があります。静的な読み取り専用を使用する方がより安全で便利です。
cfeduke、2009年

6
constの利点は、スイッチで使用できることです
knaki02

11

これがIMOの最良の方法です。プロパティは不要、または読み取り専用:

public static class Constants
{
   public const string SomeConstant = "Some value";
}

9
constを使用する場合は、内部のみとして公開してください。constを公開しないでください(アセンブリが組織の外部で使用されないと思われる場合でも)。また、プロパティは、インターフェイスを再定義する必要なく、将来の拡張に備えてプログラムの柔軟性を提供します。
cfeduke、2009年

4

空の静的クラスが適切です。複数のクラスを使用して、関連する定数の適切なグループになり、1つの巨大なGlobals.csファイルではなくなることを検討してください。

さらに、一部のint定数については、次の表記を考慮してください。

[Flags]
enum Foo
{
}

これにより、フラグのような値扱うことができます。


「いくつかのクラスを使用することを検討してください。そうすれば、1つの巨大なGlobals.csファイルではなく、関連する定数の適切なグループができあがります。」これが一番のおすすめだと思いますが、周りにデザインパターンはありませんか?名前はわかりませんよね?
集計

3

web.configまたはapp.configを使用する別の投票。構成ファイルは、接続文字列などの定数を格納するのに適した場所です。これらの種類のものを表示または変更するために、ソースを見る必要はありません。.configファイルからこれらの定数を読み取る静的クラスは、コードで定義されているかのようにアプリケーションがこれらのリソースにアクセスできるようにする一方で、それらを簡単に表示/編集できるようにする柔軟性を提供するので、良い妥協かもしれません。スペース。


2
接続文字列は定数ではなく、設定です。それはOPがある可能性があり、実際にではなく、定数よりも、あまりにも設定を意味し、私はそれのための証拠が表示されません。
Jon Skeet、

失礼ですが同意できません。文字列リテラルは、定義により定数です。構成ファイルの文字列を変更することは、コードで文字列を変更して再コンパイルすることとほぼ同じです。う、それが一定しない作りますか?私はそうは思いません。
3Dave 2009年

2
@David-真実ではない。コンパイラーは、構成ファイルにどのような値があるかを気にしません-これは実行時に読み取られます。
フィリップウォレス

@PhilipW私はそれを理解しています。私のポイントは、(Jon Skeetのコメントに応じて)すべての文字列リテラルがそうであるように、特定の接続文字列は定数であるということでした。「定数」を変更できるという事実-構成ファイルを変更し、アプリにその構成ファイルから新しい値をプルさせるか、再コンパイル/デプロイを必要とするコードのリテラルを変更することによって-変更しないそれを「設定」にします。文字列自体は、そのコンテナに関係なく一定です。私はあなたの主張を理解し同意します-それは私が言っていたものではありませんでした。
3Dave 2009年

1
私の経験では、不測の将来のある時点で、100万年後には変わらないと思っていたとしても、「一定」の値を変更する必要があります。これは、ソースコードを変更するよりも.configファイルで行う方がはるかに簡単だと思います。結局、すべてが設定になってしまいます。
NinjaBomb 2010

1

はい、static class特定の型に関連する定数を除いて、定数を格納するためのa で十分です。


それがまさに私がやろうとしていることです。彼らが所属するクラスのメンバーとして現れてほしい。ただし、定数は私が作業している会社によって異なるため、クラスに追加したくありません。拡張定数やプロパティについてはまだ何も見つかりません。しかし、これらのクラスをシリアル化するときにメンバーとして表示されたくないので、このアイデアを放棄するかもしれません
symbiont

0

これらの定数がサービスの参照またはアプリケーションの動作に影響を与えるスイッチである場合、アプリケーションのユーザー設定として設定します。そうすれば、それらを変更する必要がある場合、再コンパイルする必要がなく、静的プロパティクラスを介してそれらを参照できます。

Properties.Settings.Default.ServiceRef

0

静的な読み取り専用の静的クラスをお勧めします。以下のコードスニペットを見つけてください。

  public static class CachedKeysManager
    {
        public static readonly string DistributorList = "distributorList";
    }
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.