web-dev-qa-db-ja.com

C#静的クラスと定義済み文字列の構造体

同僚がC#で次の構造を作成しました(サンプルコードは簡略化されています)。彼の目標は、残りのコード内のすべての定義済み文字列の表記を短くすることでした。

public struct PredefinedStrings
{
    public const string VeryLongName = "Very Long Name";
    public const string AnotherVeryLongName = "Another Very Long Name";
    public const string TheLastVeryLongName = "The Last Very Long Name";
}

public static void MethodThatUsesTheNames()
{
    Console.WriteLine(PredefinedStrings.VeryLongName);
    Console.WriteLine(PredefinedStrings.AnotherVeryLongName);
    Console.WriteLine(PredefinedStrings.TheLastVeryLongName);
}

彼にとってはうまく機能しているように見えますが、構造体の代わりに静的クラスを使用すべきだったのか、これを実現するためのよりエレガントな方法があるのか​​と疑問に思わずにはいられません。

これを行うための好ましい方法は何でしょうか?理由も教えてください。

51

structソリューションでは、他のコードがnew PredefinedStrings()を実行するのを止めるものは何もありません。これは何でも悪いことではありませんが、意味的に混乱を招くものです。静的クラスでは、コンパイラーは作成を禁止します。そして言うまでもなく、静的クラスはフレームワークで定数を提供するための好ましい方法です。

編集追加すると、私はその2番目の部分を証拠なしで言った-それ以来、私は検索し、合理的に迅速に見つけたSystem.Net.Mime.DispositionTypeNamesおよびSystem.Net.WebRequestMethods.Http

43
AakashM

文字列はすべてリソースファイルにあり、コード内に埋め込まれていないことをお勧めします。これは、プロパティメンバーとして値を持つ静的クラスを介してアクセスできます。

31
Andrew

static classstructの他に、定数文字列にresourceファイルの使用を検討してみませんか?これらはSomeNamespace.ResourceName.KeyNameとして非常に簡単にアクセスでき、プロジェクトのどこにあるかに応じて、必要に応じて再コンパイルせずに外部で管理できます...

25
KP.

簡単な経験則:他に選択肢がなくなるまで、構造体を使用しないでください。

定数にはいくつかの欠点があります:

  • 使用できるのは単純型のみ(文字列、数値など)
  • 定数は参照アセンブリに挿入されます。定数を使用してアセンブリを再コンパイルし、定数を使用するアセンブリを再コンパイルしないと、問題が発生します

私はあなたのコードを次のように書きます(リファクタリングもリネームすることに注意してください):

public static class KnownNames
{
    public static readonly string VeryLong = "Very Long Name";
    public static readonly string AnotherVeryLong = "Another Very Long Name";
    public static readonly string TheLastVeryLong = "The Last Very Long Name";
}
9

リソースファイル(.resx)を探しているようです。これは、そのような文字列を格納するための適切な場所であり、文字列を.resxに抽象化すると、将来アプリケーションをローカライズしやすくなります。 http://msdn.Microsoft.com/en-us/library/1ztca10y.aspx のMSDNページは、詳細についてはまともなスタートです。

6
stack

このコードには機能的に問題はありません。しかし、文体的には静的クラスの方が良いことに同意します。静的クラスは、型の目的が静的/定数データのみを保持することであることを宣言します。

5
JaredPar

構造体のサイズは約16バイトにすることをお勧めします。 32ビットシステムの場合、これは4つのSystem.String参照です。文字列の数が増える場合は、静的クラスを使用したほうがよいと思います。

5
Jesse C. Slicer

この答え で詳述されている特定の基準を満たさない限り、構造体は通常回避されます。

同僚は値を格納するためにそれを使用していないため、構造体ではなくクラスを使用する必要があります。

2
Trisped

静的クラスは、最も標準的で期待されているため、最適な方法と思われます。私はstruct/constバージョンの方が速いかもしれないと思いましたが、いくつかのテストの後ではそうではありませんでした。

これは、長さ、比較、連結、コピー、indexOf、およびサブストリングを含む私のクイックテストの結果です。デバッガーが接続されていないリリースの.Net 4.0で実行されました。

                                          .Net 3.0  .Net 4.0
static class with static read-only string:  0.217   0.364  seconds
static class with const            string:  0.211   0.361  seconds
struct       with static read-only string:  0.211   0.372  seconds
struct       with const            string:  0.214   0.371  seconds
Properties.Resources               string:  1.173   1.268  seconds

リソースファイルを使用する場合を除いて、パフォーマンスはほぼ同じでした。 Properties.Resourcesは低速ですが、実行可能ファイルに格納されないため、場合によってはより適切な場合があります。だから私の意見では、「静的クラス」または文字列を格納するProperties.Resourcesを使用します。

1
Sunsetquest

静的の方が良いと思いますが、これが私の推論です。このコードがいくつかのライブラリに存在し、別のコードがこのライブラリを使用する場合、定数フィールドの値が変更されると、このライブラリを再コンパイルする必要があるだけでなく(これは)、これを使用するコードを再コンパイルする必要がありますライブラリも同様です。その理由は、コンパイル時に定数値が参照先に挿入されるためです。ただし、staticを使用する場合、valueではなくfieldを参照しているため、この問題は発生しません。

1
BFree

この目的のための私の練習では、Dictionary<enumNameType, string>。 enumNameTypeは、使用できる名前のタイプです(この場合)...このディクショナリは静的クラスにラップされてキャッシュされます-初めて使用するときに作成し、同じオブジェクトを返します...

これもお役に立てば幸いです!

0
anthares

私は定数にも構造体を使用していますが、パブリックAPIではなく、内部でのみ使用します。列挙型も構造体に変換されるので、自然な感じがします。

0
Max Toro

定数であることを意図した新しいオブジェクトを作成することが許可されているという単純な事実は、(通常)悪い習慣の明確な証拠です。理由は不明ですが、.NETはこの概念を時々利用するため、「通常」と言います。

もちろん、いつでも次のようなことができます。

public class Foo
{
    public struct Bar
    {
        public static double A = 100;

        public Bar(double a)
        {
            A = a;
        }
    }
}

これは、Barの作成を技術的に正当化します。ただし、定数Barが同じであること(シングルスレッド環境であっても)が保証されるわけではなく、最終的にほとんど使用されません。

0
James M