为什么C#可以在运行时处理这个明显的愚蠢对象推广?

Mik*_*erk 7 c# inheritance struct structlayout

我非常喜欢C#语言.我只是玩游戏,绝不会在生产代码中使用下面的代码.显然,编译器被结构的布局所欺骗.但是为什么Super Class上的字符串仍然可以在运行时写入和读取?我本来期望一些内存访问违规.在运行时检查类型,它表示它是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; }
    }
}
Run Code Online (Sandbox Code Playgroud)

The*_*Wes 0

好吧,你告诉 CLR 通过使用提前布局内存StructLayout我应该警告一下,这是基于我今天在实验和阅读建议的其他答案后学到的知识

您可以在这里看出 CLR 实际上并没有实例化任何东西。这将引发 NPE。你可以使用 super 的构造函数。它不会被调用,也不会被调用。

基本上,您是直接访问内存,并且由于等都是内置类型,因此您可以string安全与它们交互。这可能需要用户更多的“意图”,并且其他评论的问题都指出这需要声明。intunsafe

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; }
}
Run Code Online (Sandbox Code Playgroud)