2

Task に名前を追加するコードを書いたことがあります。以下のコードは同じように見えますが、コードが少なくなっています。しかし、それは合法なのだろうか。本番コードの準備はできていますか。ガベージコレクションはどうですか?クラスのインスタンスがコード内で移動されている場合 (固定されていないため) はどうですか?移動しても機能しますか? このコードをテストするにはどうすればよいですか?

using System.Runtime.InteropServices;

namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {
            var obj = new object();
            obj.Tag("Link some data");
            var tag = obj.Tag();
        }
    }

    public static class ObjectExtensions
    {
        private class Tagger
        {
            public string Tag { get; set; }
        }

        [StructLayout(LayoutKind.Explicit)]
        private struct Overlay
        {
            [FieldOffset(0)]
            public Tagger Tagger;
            [FieldOffset(0)]
            public object Instance;
        }

        public static string Tag(this object obj)
        {
            var overlay = new Overlay {Instance = obj };
            return overlay.Tagger.Tag;
        }

        public static void Tag(this object obj, string tag)
        {
            var overlay = new Overlay {Instance = obj };
            overlay.Tagger.Tag = tag;
        }
    }
}
4

1 に答える 1

3

いいえ、これはまったく合法ではありません。率直に言って、.NET と C# が/unsafeスイッチなしでこれを許可していることに驚いています。あなたの提案には明らかなリスクがありますが、ここ数年の C# でのコーディングの中で、安全でないコードを明示的に有効にせずに、C# でこのように安全なメモリ アクセスを侵害できるとは思いもしませんでした。

あなたの例でこのバリエーションを考えてみましょう:

class A
{
    public string Text { get; set; }
}

class Program
{
    static void Main(string[] args)
    {
        A a = new A { Text = "Text" };

        a.Tag("object A tag");

        string tag = a.Tag(), text = a.Text;
    }
}

最後のステートメントで、text変数が に設定されていることがわかります"object A Tag"。つまり、「オーバーレイ」アプローチにより、コードは class のオブジェクトへの参照を class のオブジェクトへの参照として再解釈できAOverlayコンパイラの警告や実行時エラーはまったく発生しません。

上記の例では、結果はあなたが期待できるほど無害です: の元のプロパティ値はText、正しい値から「タグ」として渡されたテキストに変更されています。これは十分に悪いことですが、他のコンテキストでは、クラスがひどい方法で破損していることに気付く可能性があり、さらにデータが破損したり、(運が良ければ) ある種のアクセス違反やその他の例外が原因でプログラムが即座に終了したりする可能性があります.

これをしないでください。これは非常に危険であり、ここで提案した方法で使用すると、正しく動作しません。必要のないデータを常に上書きすることになります。

于 2017-04-07T23:55:18.523 に答える