Почему 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; }
}
Другие вопросы по тегам