次のようなものを書くことは可能ですか?
public const string[] Titles = { "German", "Spanish", "Corrects", "Wrongs" };
はい、でもreadonly
ではなくconst
と宣言する必要があります。
public static readonly string[] Titles = { "German", "Spanish", "Corrects", "Wrongs" };
その理由は、const
はコンパイル時に値がわかっているフィールドにしか適用できないからです。ここに示した配列初期化子はC#では定数式ではないため、コンパイラエラーが発生します。
宣言するとreadonly
はその問題を解決します。実行時まで値が初期化されないからです(ただし、配列が最初に使用される前に初期化されることが保証されています)。
最終的に達成したいことによっては、enumを宣言することを検討することもできます。
public enum Titles { German, Spanish, Corrects, Wrongs };
配列をreadonly
として宣言できますが、readonly
配列の要素を変更できることに注意してください。
public readonly string[] Titles = { "German", "Spanish", "Corrects", "Wrongs" };
...
Titles[0] = "bla";
Codyが提案しているようにenum、またはIListを使用することを検討してください。
public readonly IList<string> ITitles = new List<string> {"German", "Spanish", "Corrects", "Wrongs" }.AsReadOnly();
配列はオブジェクトであり、実行時にのみ作成でき、constエンティティはコンパイル時に解決されるため、 'const'配列を作成することはできません。
代わりにできることは、配列を "readonly"として宣言することです。実行時に値を設定できることを除けば、constと同じ効果があります。それは一度だけ設定することができ、その後それは読み取り専用(すなわちconst)値である。
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[]) Titles)[1] = "French";
別の方法をとることもできます。配列を表す定数文字列を定義し、必要に応じて文字列を配列に分割します。
const string DefaultDistances = "5,10,15,20,25,30,40,50";
public static readonly string[] distances = DefaultDistances.Split(',');
この方法では、構成に格納し、必要に応じて配列に変換できる定数が得られます。
アラステア
IReadOnlyListインターフェイスの背後で配列を宣言すると、実行時に宣言された定数値を持つ定数配列が得られます。
public readonly IReadOnlyList<string> Titles = new [] {"German", "Spanish", "Corrects", "Wrongs" };
.NET 4.5以降で利用可能です。
tdbeckett's answer を改善する.NET Framework v4.5 +ソリューション:
using System.Collections.ObjectModel;
// ...
public ReadOnlyCollection<string> Titles { get; } = new ReadOnlyCollection<string>(
new string[] { "German", "Spanish", "Corrects", "Wrongs" }
);
注:コレクションが概念的に一定であることを考えると、classレベルで宣言するためにstatic
にすることは理にかなっています。
上記:
プロパティの暗黙的なバッキングフィールドを初期化しますonce配列を使用します。
{ get; }
-つまり、プロパティのみを宣言するgetter-は、プロパティ自体を暗黙的に読み取り専用にするものであることに注意してください(readonly
と{ get; }
を組み合わせようとすると、実際には構文エラーになります)。
または、{ get; }
を省略してreadonly
を追加し、質問のようにプロパティの代わりにフィールドを作成することもできますが、publicデータメンバーをフィールドではなくプロパティとして公開するのが適切です形成する習慣。
array-like structure(インデックス付きアクセスを許可)を作成します。これはtrulyおよび堅牢に読み取り専用です。(概念的には1回、作成)、両方に関して:
IReadOnlyList<T>
ソリューションとは異なり、a (string[])
キャストを使用して、 mjepsenの有用な回答 に示すように、elements。IReadOnlyCollection<T>
インターフェイスにも適用されます。これは、名前がクラスに類似しているにも関わらずReadOnlyCollection
、indexed accessもサポートしていないため、配列のようなアクセスを提供するには基本的に不適切です。)私のニーズに合わせて、不可能なstatic
ではなくconst
配列を定義していますが、うまくいきます:public static string[] Titles = { "German", "Spanish", "Corrects", "Wrongs" };
これはあなたが望むことをする方法です:
using System;
using System.Collections.ObjectModel;
using System.Collections.Generic;
public ReadOnlyCollection<string> Titles { get { return new List<string> { "German", "Spanish", "Corrects", "Wrongs" }.AsReadOnly();}}
読み取り専用の配列を作成するのとよく似ています。
私はあなたがそれをただ読み取り専用にすることができると信じます。
完全を期すために、今はImmutableArrayも自由に使用できます。これは本当に不変であるべきです:
public readonly static ImmutableArray<string> Tiles = ImmutableArray.Create(new[] { "German", "Spanish", "Corrects", "Wrongs" });
System.Collections.Immutable NuGetリファレンスが必要です
https://msdn.Microsoft.com/ja-jp/library/mt452182(v=vs.111).aspx
配列はおそらく実行時にしか評価できないものの1つです。定数はコンパイル時に評価されなければなりません。 "const"の代わりに "readonly"を使ってみてください。
別の方法として、読み取り専用配列で要素を変更できるという問題を回避するには、代わりに静的プロパティを使用できます。 (個々の要素はまだ変更可能ですが、これらの変更は配列のローカルコピーに対してのみ行われます。)
public static string[] Titles
{
get
{
return new string[] { "German", "Spanish", "Corrects", "Wrongs"};
}
}
もちろん、毎回新しい文字列配列が作成されるので、これは特に効率的ではありません。