像这样标记对象是合法代码吗?

Is it legit code to tag an object like this?

我曾经写过一篇code to add a name to a Task。下面的代码似乎做同样的事情,但代码更少。但我想知道,这是合法的。生产代码准备好了吗?垃圾回收呢? class 的实例在代码中四处移动(因为它没有被固定)怎么样,当它四处移动时它仍然有效吗?如何测试此代码?

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;
        }
    }
}

不,这根本不合法。坦率地说,令我惊讶的是 .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"。换句话说,您的 "overlay" 方法允许您的代码将对 class A 对象的引用重新解释为对 class [=15= 对象的引用], 没有任何类型的编译器警告或 运行-time 错误。

在上面的示例中,结果与您希望的一样好:Text 的原始 属性 值已从其正确值更改为作为 "tag"。这已经够糟糕了,但在其他情况下,您可能会发现您的 class 已以可怕的方式损坏,导致进一步的数据损坏或(如果您幸运的话)由于某种访问而导致您的程序立即终止违规或其他异常。

不要这样做。这是非常危险的,当然,当按照您在此处建议的方式使用时,永远不会 正常工作。你总是会覆盖一些你不应该拥有的数据。