我非常喜欢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 上的构造函数。它不会被调用,也不会。
基本上您是在直接访问内存,并且由于 string
、int
等都是内置类型,您可以安全 与它们进行交互。这可能需要用户更多的“意图”,其他评论的问题都指向这需要 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/