回答:
はい。ただし、次のreadonly
代わりに宣言する必要がありますconst
。
public static readonly string[] Titles = { "German", "Spanish", "Corrects", "Wrongs" };
その理由は、const
コンパイル時に値がわかっているフィールドにのみ適用できるためです。表示した配列初期化子はC#の定数式ではないため、コンパイラエラーが発生します。
readonly
値は実行時まで初期化されないため、宣言するとこの問題が解決されます(ただし、配列が初めて使用される前に初期化されていることが保証されています)。
最終的に達成したいものに応じて、列挙型の宣言を検討することもできます。
public enum Titles { German, Spanish, Corrects, Wrongs };
readonly static
要求されたセマンティクスに似ている必要があります。
static
はそれを機能させる必要はありません、Titles
インスタンスなしで参照する可能性を追加するだけで、異なるインスタンスの値を変更する可能性を削除します(たとえば、readonly
フィールドの値を変更するパラメーターに応じてコンストラクターを持つことができます)。
配列はとして宣言できreadonly
ますが、readonly
配列の要素は変更できることに注意してください。
public readonly string[] Titles = { "German", "Spanish", "Corrects", "Wrongs" };
...
Titles[0] = "bla";
Codyが示唆するように、列挙型またはIListの使用を検討してください。
public readonly IList<string> ITitles = new List<string> {"German", "Spanish", "Corrects", "Wrongs" }.AsReadOnly();
const
NOT についてreadonly
です...
配列はオブジェクトであり、実行時にのみ作成でき、constエンティティはコンパイル時に解決されるため、「const」配列を作成することはできません。
代わりにできることは、配列を「読み取り専用」として宣言することです。これは、値を実行時に設定できることを除いて、constと同じ効果があります。これは一度だけ設定でき、その後は読み取り専用(つまりconst)の値になります。
const int[] a = null;
は、あまり役に立ちませんが、実際には配列定数のインスタンスです。
C#6以降、次のように記述できます。
public static string[] Titles => new string[] { "German", "Spanish", "Corrects", "Wrongs" };
参照:C#:新しく改善されたC#6.0(具体的には、「式本体関数とプロパティ」の章)
これにより、読み取り専用の静的プロパティが作成されますが、返される配列の内容を変更できますが、プロパティを再度呼び出すと、元の変更されていない配列が再び取得されます。
明確にするために、このコードは以下と同じです(または実際の省略形)。
public static string[] Titles
{
get { return new string[] { "German", "Spanish", "Corrects", "Wrongs" }; }
}
このアプローチにはマイナス面があることに注意してください。新しい配列は実際にはすべての参照でインスタンス化されるため、非常に大きな配列を使用している場合、これは最も効率的なソリューションではない可能性があります。ただし、同じ配列を(たとえば、プライベート属性に配置することによって)再利用すると、配列の内容を変更する可能性が再び開かれます。
不変の配列(またはリスト)が必要な場合は、次も使用できます。
public static IReadOnlyList<string> Titles { get; } = new string[] { "German", "Spanish", "Corrects", "Wrongs" };
ただし、これを変更して、string []にキャストバックして内容を変更できるため、変更のリスクがあります。
((string[]) Titles)[1] = "French";
Titles[0]
ます。たとえば、に割り当ててもコンパイルエラーが発生しません-実際には、割り当ての試行は静かに無視されます。毎回アレイを再作成する非効率性と組み合わせると、このアプローチは示す価値があるのでしょうか。対照的に、2番目のアプローチは効率的であり、不変性を打ち負かすために自分の道を離れなければなりません。
IReadOnlyListインターフェイスの背後で配列を宣言すると、実行時に宣言された定数値を持つ定数配列が得られます。
public readonly IReadOnlyList<string> Titles = new [] {"German", "Spanish", "Corrects", "Wrongs" };
.NET 4.5以降で使用できます。
A +ソリューションの.NET FrameworkのV4.5に向上tdbeckettの答え:
using System.Collections.ObjectModel;
// ...
public ReadOnlyCollection<string> Titles { get; } = new ReadOnlyCollection<string>(
new string[] { "German", "Spanish", "Corrects", "Wrongs" }
);
注:コレクションが概念的に一定であることを考えるとstatic
、クラスレベルで宣言するようにコレクションを作成することは理にかなっています。
上記:
プロパティの暗黙のバッキングフィールドを配列で一度初期化します。
{ get; }
プロパティゲッターのみを宣言すると、プロパティ自体が暗黙的に読み取り専用になることに注意してください(実際にを組み合わせようとするreadonly
と{ get; }
、構文エラーになります)。
または、質問のように、プロパティの代わりにフィールドを作成して{ get; }
追加readonly
するだけで、パブリックデータメンバーをフィールドではなくプロパティとして公開することをお勧めします。
次の両方に関して、真にかつ堅牢に読み取り専用(概念的には定数で、一度作成されると)の配列のような構造(インデックス付きアクセスを許可)を作成します。
IReadOnlyList<T>
ソリューション、キャストが要素にゲインの書き込みアクセスに使用することができますに示すように、mjepsenの便利な答え。
同じ脆弱性が適用されるインタフェース名の類似性にもかかわらず、これは、クラス、でもサポートされていないインデックス付きのアクセスを配列のようなアクセスを提供するための、それは根本的に適しません、。)(string[])
IReadOnlyCollection<T>
ReadOnlyCollection
IReadOnlyCollection
インデックス付きアクセスをサポートしていないため、ここでは使用できません。さらに、IReadOnlyList
(インデックス付きアクセスを持っている)のように、にキャストバックすることによる要素操作の影響を受けやすくなっていますstring[]
。つまり、ReadOnlyCollection
(文字列配列をキャストできない)が最も堅牢なソリューションです。ゲッターを使用しないことはオプションです(そして、私はそれを注記するために答えを更新しました)が、パブリックデータでは、おそらくプロパティに固執する方が良いでしょう。
私のニーズのためstatic
に、不可能ではなく配列を定義しconst
、それが機能します:
public static string[] Titles = { "German", "Spanish", "Corrects", "Wrongs" };
const
OPの例から単純に削除することもできますが、それ(またはあなたの答え)により、Titles
インスタンスと任意の値の両方を変更できます。それでは、この回答のポイントは何ですか?
readonly
const
readonly
const
const
別のアプローチを取ることもできます。たとえば、配列を表す定数文字列を定義し、必要に応じて文字列を配列に分割します。
const string DefaultDistances = "5,10,15,20,25,30,40,50";
public static readonly string[] distances = DefaultDistances.Split(',');
このアプローチでは、構成に格納して必要に応じて配列に変換できる定数が提供されます。
完全を期すために、ImmutableArrayも自由に使えるようになりました。これは本当に不変でなければなりません:
public readonly static ImmutableArray<string> Tiles = ImmutableArray.Create(new[] { "German", "Spanish", "Corrects", "Wrongs" });
System.Collections.Immutable NuGet参照が必要です
https://msdn.microsoft.com/en-us/library/mt452182(v=vs.111).aspx
これはあなたが望むことをする方法です:
using System;
using System.Collections.ObjectModel;
using System.Collections.Generic;
public ReadOnlyCollection<string> Titles { get { return new List<string> { "German", "Spanish", "Corrects", "Wrongs" }.AsReadOnly();}}
これは、読み取り専用の配列を行うことと非常に似ています。
public static readonly ReadOnlyCollection<String> Titles = new List<String> { "German", "Spanish", "Corrects", "Wrongs" }.AsReadOnly();
; とにかくそれをReadOnlyCollectionにすれば、毎回の検索でリストを再作成する必要はありません。
最良の選択肢:
public static readonly byte[] ZeroHash = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };