为什么 C# 可以在运行时处理这种明显愚蠢的对象提升



我非常喜欢C#语言。我只是在玩,永远不会在生产代码中使用以下代码。显然,编译器被结构的布局所愚弄。但是,为什么超级类上的字符串仍然可以在运行时写入和读取呢?我本来希望会有一些内存访问冲突。在运行时检查类型,它说它是 Base 类型,请参阅NoProblem()函数执行。尚未实例化任何超类。

它怎么能这样运作?

using System;
using System.Runtime.InteropServices;
namespace Fiddle
{
    class Program
    {
        static void Main(string[] args)
        {
            var b = new Base
            {
                IntOnBase = 1
            };
            var overlay = new Overlay();
            overlay.Base = b;
            var super = overlay.Super;
            var intValue = super.IntOnBase;
            super.StringOnSuper = "my test string";
            var stringValue = super.StringOnSuper;
            super.NoProblem();
            Expressions.Fiddle();
        }
    }
    [StructLayout(LayoutKind.Explicit)]
    public struct Overlay
    {
        [FieldOffset(0)]
        public Super Super;
        [FieldOffset(0)]
        public Base Base;
    }
    public class Super : Base
    {
        public string StringOnSuper { get; set; }
        public void NoProblem()
        {
            Console.WriteLine("You know, I am really a " + this.GetType().Name + " kind of class.");
        }
    }
    public class Base
    {
        public int IntOnBase { get; set; }
    }
}

好吧,您告诉 CLR 使用StructLayout提前布置内存(我应该警告这个说法,这是基于我今天在实验和阅读其他建议的答案后学习的(

您可以在此处判断 CLR 实际上并未实例化任何内容。这将引发一个 NPE。你可以在 super 上玩弄构造函数。它不会被调用,也不会被调用。

基本上,您直接访问内存,并且由于stringint等都是内置的类型,因此您可以安全地与它们进行交互。这可能需要用户更多的"意图",其他注释的问题都指向这需要unsafe声明。

class Program
{
    static void Main(string[] args)
    {
        var b = new Base
        {
            IntOnBase = 1
        };
        var overlay = new Overlay();
        overlay.Base = b;
        var super = overlay.Super;
        var intValue = super.IntOnBase;
        super.StringOnSuper = 8;
        var stringValue = super.StringOnSuper;
        System.Diagnostics.Debug.WriteLine(stringValue);
        super.NoProblem();
    }
}
[StructLayout(LayoutKind.Explicit)]
public struct Overlay
{
    [FieldOffset(0)]
    public Super Super;
    [FieldOffset(0)]
    public Base Base;
}
public class NewClass
{
    public string cat { get; set; }
}
public class Super : Base
{
    private Super imNull;
    public Super()
    {
       // imNull = new Super();
        System.Diagnostics.Debug.WriteLine("well i get initialized...");
    }
    public int StringOnSuper { get; set; }
    public void NoProblem()
    {
        System.Diagnostics.Debug.Write("You know, I am really a " + this.GetType().Name + " kind of class. But my super is " + imNull.ToString() );
    }
}
public class Base
{
    public int IntOnBase { get; set; }
}

相关内容

  • 没有找到相关文章

最新更新