同僚が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);
}
彼にとってはうまく機能しているように見えますが、構造体の代わりに静的クラスを使用すべきだったのか、これを実現するためのよりエレガントな方法があるのかと疑問に思わずにはいられません。
これを行うための好ましい方法は何でしょうか?理由も教えてください。
struct
ソリューションでは、他のコードがnew PredefinedStrings()
を実行するのを止めるものは何もありません。これは何でも悪いことではありませんが、意味的に混乱を招くものです。静的クラスでは、コンパイラーは作成を禁止します。そして言うまでもなく、静的クラスはフレームワークで定数を提供するための好ましい方法です。
編集追加すると、私はその2番目の部分を証拠なしで言った-それ以来、私は検索し、合理的に迅速に見つけたSystem.Net.Mime.DispositionTypeNames
およびSystem.Net.WebRequestMethods.Http
。
文字列はすべてリソースファイルにあり、コード内に埋め込まれていないことをお勧めします。これは、プロパティメンバーとして値を持つ静的クラスを介してアクセスできます。
static class
とstruct
の他に、定数文字列にresource
ファイルの使用を検討してみませんか?これらはSomeNamespace.ResourceName.KeyName
として非常に簡単にアクセスでき、プロジェクトのどこにあるかに応じて、必要に応じて再コンパイルせずに外部で管理できます...
簡単な経験則:他に選択肢がなくなるまで、構造体を使用しないでください。
定数にはいくつかの欠点があります:
私はあなたのコードを次のように書きます(リファクタリングもリネームすることに注意してください):
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";
}
リソースファイル(.resx)を探しているようです。これは、そのような文字列を格納するための適切な場所であり、文字列を.resxに抽象化すると、将来アプリケーションをローカライズしやすくなります。 http://msdn.Microsoft.com/en-us/library/1ztca10y.aspx のMSDNページは、詳細についてはまともなスタートです。
このコードには機能的に問題はありません。しかし、文体的には静的クラスの方が良いことに同意します。静的クラスは、型の目的が静的/定数データのみを保持することであることを宣言します。
構造体のサイズは約16バイトにすることをお勧めします。 32ビットシステムの場合、これは4つのSystem.String参照です。文字列の数が増える場合は、静的クラスを使用したほうがよいと思います。
この答え で詳述されている特定の基準を満たさない限り、構造体は通常回避されます。
同僚は値を格納するためにそれを使用していないため、構造体ではなくクラスを使用する必要があります。
静的クラスは、最も標準的で期待されているため、最適な方法と思われます。私は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を使用します。
静的の方が良いと思いますが、これが私の推論です。このコードがいくつかのライブラリに存在し、別のコードがこのライブラリを使用する場合、定数フィールドの値が変更されると、このライブラリを再コンパイルする必要があるだけでなく(これは)、これを使用するコードを再コンパイルする必要がありますライブラリも同様です。その理由は、コンパイル時に定数値が参照先に挿入されるためです。ただし、staticを使用する場合、valueではなくfieldを参照しているため、この問題は発生しません。
この目的のための私の練習では、Dictionary<enumNameType, string>
。 enumNameTypeは、使用できる名前のタイプです(この場合)...このディクショナリは静的クラスにラップされてキャッシュされます-初めて使用するときに作成し、同じオブジェクトを返します...
これもお役に立てば幸いです!
私は定数にも構造体を使用していますが、パブリックAPIではなく、内部でのみ使用します。列挙型も構造体に変換されるので、自然な感じがします。
定数であることを意図した新しいオブジェクトを作成することが許可されているという単純な事実は、(通常)悪い習慣の明確な証拠です。理由は不明ですが、.NETはこの概念を時々利用するため、「通常」と言います。
もちろん、いつでも次のようなことができます。
public class Foo
{
public struct Bar
{
public static double A = 100;
public Bar(double a)
{
A = a;
}
}
}
これは、Bar
の作成を技術的に正当化します。ただし、定数Bar
が同じであること(シングルスレッド環境であっても)が保証されるわけではなく、最終的にほとんど使用されません。