Почему C# может справиться с этим явно идиотским продвижением объектов во время выполнения?
Мне очень нравится язык C#. Я просто играю вокруг, и никогда не буду использовать код ниже в производственном коде. Очевидно, что компилятор одурачен компоновкой структуры. Но почему получается, что строка в классе Super все еще может быть записана и прочитана во время выполнения? Я бы ожидал некоторое нарушение доступа к памяти. Проверяя тип во время выполнения, он говорит, что он имеет тип 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; }
}
}
1 ответ
Ну, вы сказали CLR, чтобы выложить память заранее с помощью StructLayout
(Я должен предупредить, что это основано на моем сегодняшнем обучении после экспериментов и прочтения других предложенных ответов)
Здесь вы можете сказать, что CLR на самом деле ничего не создает. Это бросит NPE. И вы можете поиграть с конструктором на супер. Это не вызывается и не будет.
По сути, вы напрямую обращаетесь к памяти, и с 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; }
}