readonly
リフレクションを使用してフィールドの値を変更できるのに、a の値を変更できないのはなぜconst
ですか?
class Program
{
static void Main(string[] args)
{
Foobar foobar = new Foobar();
Console.WriteLine(foobar.foo); // Outputs "Hello"
Console.WriteLine(Foobar.bar); // Outputs "Hello"
var field = foobar.GetType().GetField("foo");
field.SetValue(foobar, "World"); // Ok
field = foobar.GetType().GetField("bar");
field.SetValue(foobar, "World"); // Throws FieldAccessException
Console.ReadKey();
}
}
public class Foobar
{
public readonly string foo = "Hello";
public const string bar = "Hello";
}
この回答を読んだので、ルールを破ることが許可されていることは理解していますが、その場合はreadonly
なぜですか? const
正当な理由があると確信していますが、それが何であるかはわかりません。
- 編集 -
ildasm を使用して上記のコードを見ると、readonly
コンパイル時にフィールドの値が設定されています。とは異なり、フィールド自体ではconst
なく、クラスのコンストラクターで。そのため、一方を「上書き」できるのに、もう一方を上書きできない理由がわかりません。
つまり、値がconst
バイナリで「ハードコード」されていても、「既に設定されている」ため、または単に設計上の決定であるため、フレームワーク自体の技術的な制限を変更できない理由です。const
のためにそれを行っているので、どこかに を変更する「魔法」が存在しない理由はわかりませんreadonly
。
-- 編集 2 --
受け入れられた回答に追加するために、非常に興味深いこの他の回答もあります。この質問をしたときに最初に得られなかったのは、コード内で使用されている場所の背後にある値const
が実際に置き換えられるということです。この宣言では:
public const string Foo = "Hello";
後で書く
Console.WriteLine(Foo);
書くことに等しい
Console.WriteLine("Hello");
確かに私のコード
Console.WriteLine(foobar.foo);
Console.WriteLine(Foobar.bar);
ILでは次のように置き換えられます
IL_0008: ldfld string ConsoleApplication3.Foobar::foo
IL_000d: call void [mscorlib]System.Console::WriteLine(string)
IL_0012: nop
IL_0013: ldstr "Hello"
IL_0018: call void [mscorlib]System.Console::WriteLine(string)