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

标签 c# inheritance struct structlayout

我非常喜欢C#语言。我只是在玩,永远不会在生产代码中使用下面的代码。显然,编译器被结构的布局所愚弄。但是,为什么 Super 类上的字符串仍然可以在运行时写入和读取?我会预料到一些内存访问冲突。在运行时检查类型,它说它是 Base 类型,查看 NoProblem() 函数执行。没有实例化父类(super class)。

它是如何实现这样的功能的?

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

关于c# - 为什么 C# 可以在运行时处理这种明显愚蠢的对象提升?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43280487/

相关文章:

c# - 为什么 GDI 不允许我删除大图像?

c# - 如何实现具有注入(inject)功能的通用结构层次结构

c# 客户端使用 linq 支持使用 OData

c# - 无法在 mvc 5 项目中添加新模型和更新数据库?

javascript - 关于 JavaScript 继承的困惑

python - Python 中的 BaseException 子类问题

c - 使用结构读取文件时出现问题

java - super.a = b 而不是 super(b)

c - 如何正确地为函数中的结构分配内存以返回其值供以后使用以及如何将结构转换为指针?

c++ - 检查结构数组是否为空