定数は変更されません:dotNetの深さへの小さな余談

画像 ご挨拶。 私は最近、 Dywarの記事「C#とCLRに関する興味深いメモ」に 出会い、 13段落目に興味を持ちました。



定数はアセンブリのメタデータに配置されるため、変更があった場合は、それを使用してすべてのアセンブリを再コンパイルする必要があります。 なぜなら 定数を持つDLLはロードされない場合があります。



さあ、私は考えて、実験のために登りました。 TestConstantsプロジェクトを作成し、その中にクラス、



public class Master { public const string Const = "Hello world"; }
      
      





次に、TestConstantsSlaveプロジェクト、



 static void Main() { Console.WriteLine(Master.Const); Console.ReadKey(); }
      
      





定数を「Hello habr」に置き換え、F5で起動されたメインプロジェクトを再構築しました...



「Hello habr」がコンソールに表示されました。 どうやら、スタジオとスレーブプロジェクトが同時に再構築されたようです。 原則として、これで落ち着くことができますが、少し実験したかったです。



まず、定数を「Greetings、sir von Neumann」に置き換え、メインプロジェクトを再構築し、Explorer→TestConstantsSlave.exeでSlaveを起動しました。 「Hello habr」がコンソールで点灯していました。素晴らしいノイマンが私を許してくれたかもしれません。 最新のライブラリをスレーブにコピーしました-まだ「Hello habr」です。 TestConstantsライブラリを削除しました-再び「Hello habr」。 ハブルは黙っていました。



定数は本当にメタデータにコピーされていますか? ildasmを開きます。 スレーブマニフェストでは、すべてが標準です:バージョン、ヘッダー、トークン。 定数はありません(合理的です)。 クラスを実行しました-メタデータが明示的に見つかりませんでした。



しかし、スレーブコードには明示的に「Hello habr」があります。



錯乱



msdnのldstr命令の説明を参照してください。 「メタデータに保存されている文字列リテラルへの新しいオブジェクト参照をプッシュします」。 明らかに、ildasmのメタデータは隠されています。 念のため、dotPeekをチェックしました-結果は似ています(ただし、スレーブプロジェクトがTestConstantsを参照していないことは明らかです)。



別のタイプの定数をチェックする:Int32定数を使用すると、別のilコードldc.i4.5が得られます。 ここで、スタックへのIntaの単純なプッシュがあります(これも合理的です-行は長く、キャッシュするのが理にかなっていますが、キャッシュからIntaをプルするオーバーヘッドが排気を上回ります)。 どうやら、元の記事とmsdnで、メタデータは文字列インターンメカニズム( tunatyntz )の一部を指しているため、 ildasmにメタデータがないことを説明しています-プロセスに対して文字列プールが生成されます。



それでは、次は何ですか?



心配する必要はありません。 スタジオは正しく構築され、定数は毎日変更されません。 一方、私はすでに、SDKとそれを使用するユーティリティが異なるソリューションに含まれているプロジェクトに取り組んでいました。SDKを更新すると、「絶え間ないバグ」が発生する可能性がありました。



All Articles