Dlaczego można modyfikować wartość pola readonly
za pomocą odbicia, ale nie wartości const
?Dlaczego możliwa jest zmiana wartości pola tylko do odczytu, ale nie wartości stałej za pomocą odbicia?
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";
}
Czytałem this answer więc rozumiem to wolno łamać zasady readonly
ale dlaczego nie dla const
w tym przypadku? Jestem pewien, że istnieje dobry powód, ale nie wiem, co to może być.
- Edit -
Kiedy przyjrzeć się powyższym kodzie za pomocą ildasm wartość pola readonly
jest ustawiony w czasie kompilacji. Nie na samym polu, w przeciwieństwie do modelu const
, ale w konstruktorze klasy. Nie wiem, dlaczego można "nadpisać" jeden, ale nie drugi.
Co mam na myśli to, że nawet wartość const
jest "zakodowana" w pliku binarnym, jest powodem, że nie jest w stanie zmodyfikować jej ograniczenia technicznego w samej strukturze, ponieważ "jest już ustawiona" lub tylko decyzja projektowa. Nie widzę żadnego powodu, dla którego nie mogłaby istnieć jakaś "magia" gdzieś modyfikująca const
, tak jak robi to dla readonly
.
- Edycja 2 -
Aby dodać do przyjętej odpowiedź, nie jest również this other answer który jest dość interesująca. To, czego nie dostałem na pierwszym miejscu, zadając to pytanie, to fakt, że wartość const
jest wymieniona wszędzie tam, gdzie jest używana w kodzie. Z niniejszym oświadczeniem:
public const string Foo = "Hello";
pisanie później
Console.WriteLine(Foo);
jest równoważne formie pisemnej
Console.WriteLine("Hello");
Rzeczywiście mój kod
Console.WriteLine(foobar.foo);
Console.WriteLine(Foobar.bar);
otrzymuje IL przez
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)
Zobacz też: [Jaka jest różnica między const a readonly?] (Http://stackoverflow.com/questions/55984/what-is-the-difference-between-const-and-readonly) –
@CodyGray Dzięki dla twojego linku. Nie wiedziałem, w jaki sposób pamięć została obsłużona dla "const" i jaki wpływ może mieć na inne zgromadzenia. Modyfikowanie wartości 'const' może mieć nieznany wpływ na inne zespoły, jak sądzę. – Guillaume