【发布时间】:2017-09-02 23:28:12
【问题描述】:
我非常喜欢 C# 语言。我只是在玩,永远不会在生产代码中使用下面的代码。显然编译器被结构的布局所迷惑。但是为什么 Super 类上的字符串仍然可以在运行时读写呢?我会预料到一些内存访问冲突。在运行时检查类型,它说它是 Base 类型,请参阅NoProblem() 函数执行。没有实例化 Super 类。
它怎么能这样运作?
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; }
}
}
【问题讨论】:
-
Super 比 Base 大,如果您尝试将 Super 转换为 Base,您只会遇到问题
-
super.StringOnSuper在你分配它之前的值是多少?我希望它未初始化,因为Base的构造函数不知道它。 -
看起来类似于this question。有人建议使用
FieldOffset应视为unsafe。 -
这不是 C# 功能,语言规范一次也没有提及。这是 CLR 公开的一项功能。它有一个非常实际的需求,它声明了一个 union,这是一种在许多其他语言中都可用的类型。但不是 C#,联合从根本上说是类型不安全的。在例如 winapi 中得到大量使用,如果没有它,他们就无法编写 .NET Framework。在纯粹之上,C# 也是一种解决实际编程问题的非常实用的语言。现实世界并不纯粹。
标签: c# inheritance struct structlayout