なぜ次のことができないのだろうか:
struct TestStruct
{
public readonly object TestField;
}
TestStruct ts = new TestStruct {
/* TestField = "something" // Impossible */
};
オブジェクト初期化子はフィールドの値を設定できるべきではありませんか?
これは不可能です。またはreadonly
以外からフィールドを割り当てることができないためです。Constructor
Field Initializer
あなたが示すのは実際object initializer
です。それは単なるシンタティックシュガーであり、このようなものにまとめられます
TestStruct ts;
TestStruct ts1 = new TestStruct();
ts1.TestField = value;
ts = ts1;
コンパイルできない理由は明らかですか?
オブジェクト初期化子は初期化の簡単な方法にすぎないため:
TestStruct ts = new TestStruct {
TestField = "something";
};
と同じです(コンパイラは上記をこれに変換します):
TestStruct ts = new TestStruct();
ts.TestField = "something";//this is of course not allowed.
readonly フィールドが CollectionBase を拡張する場合、これに対する興味深い「例外」に出くわしました。
コードは次のとおりです。
using System.Collections;
namespace ReadOnly
{
class Program
{
static void Main(string[] args)
{
Foo foo1 = new Foo()
{
Bar = new Bar() // Compile error here - readonly property.
{
new Buzz() { Name = "First Buzz" }
}
};
Foo foo2 = new Foo()
{
Bar = // No Compile error here.
{
new Buzz { Name = "Second Buzz" }
}
};
}
}
class Foo
{
public Bar Bar { get; }
}
class Bar : CollectionBase
{
public int Add(Buzz value)
{
return List.Add(value);
}
public Buzz this[int index]
{
get { return (Buzz)List[index]; }
set { List[index] = value; }
}
}
class Buzz
{
public string Name { get; set; }
}
}
Foo1 は私が最初にやろうとした方法です (これらのクラスはすべて外部ライブラリから取得したため、最初は Bar が読み取り専用であることを知りませんでした)。コンパイルエラーが発生しました。その後、誤って foo2 のように再入力したところ、機能しました。
dll を逆コンパイルし、Bar が CollectionBase を拡張したことを確認した後、2 番目の構文 (foo2) がコレクションの Add メソッドを呼び出していることに気付きました。したがって、コレクションの場合、読み取り専用のプロパティを設定することはできませんが、オブジェクト初期化子を介して Add メソッドを呼び出すことができます。