偶然、http://twitter.com/#!/neuecc/statuses/76605738260242432というページを見てしまったので、C#で通るように書き直して検証してみました。
using System;
class Program
{
static void Main(string[] args)
{
Console.WriteLine(string.Empty);
typeof(string).GetField("Empty").SetValue(null, "New Empty Value");
Console.WriteLine(string.Empty);
}
}
実行結果 §
(空行)
New Empty Value
というわけで、readonlyだから変更できないというわけでも無いようです。リフレクションでイチコロ。
しかし、まだまだ甘かった。検証中に気付いてしまいました。
更なる悪夢 §
using System;
class Program
{
static void Main(string[] args)
{
typeof(string).GetField("Empty").SetValue(null, "New Empty Value");
Console.WriteLine("{0}","");
}
}
実行結果 §
New Empty Value
はい。Mainメソッドの1行目で確かにEmptyの値は上書きしていますが、2行目の出力にstring.Emptyは一切関与していません。しかし、書き換えた値が使用されています。実はこれ、値の問題なので変数を経由しても同じ事です。つまり、以下のように書いても結果は同じ。
using System;
class Program
{
static void Main(string[] args)
{
typeof(string).GetField("Empty").SetValue(null, "New Empty Value");
string s = "";
Console.WriteLine("{0}",s);
}
}
.NET Frameworkのフォーマット機能がどのような実装になっているか知りませんが、けっこうホラーな話です。
とりあえず、いくら書き換えられても特定の値が期待されているフィールドは変えるべきではないのでしょう。
ちょっとだけ考察 §
readonlyは実は読み出し専用では無く、書き換えられます。初期化とコンストラクタからであれば、いくらでも違う値を入れられます。そこがconstと違うところ。だから、readonlyでも書き換える手段はあるのかもしれませんが、おそらくconstには無いでしょう。