2014-11-28 4 views
1

Im Мессинг Arround с structlayouts и я нашел некоторые вещи я найти довольно странно:FatalExecutionEngineError когда Мессинг с StructLayouts

Следующий код работает так, как я думал, что это будет:

using System; 
using System.Runtime.InteropServices; 
public class Program 
{ 
    [STAThread] 
    static void Main() 
    { 
     Magic m = new Magic 
     { 
      InstanceA = new ClassA(), 
      InstanceB = new ClassB {Value="47"} 
     }; 

     Console.WriteLine(m.InstanceA.Value); 
     Console.ReadKey(); 
    } 

    class ClassA 
    { 
     public dynamic Value; 
    } 

    class ClassB 
    { 
     public string Value; // Change to int and it will get messy 
    } 

    [StructLayout(LayoutKind.Explicit)] 
    struct Magic 
    { 
     [FieldOffset(0)] 
     public ClassA InstanceA; 
     [FieldOffset(0)] 
     public ClassB InstanceB; 
    } 
} 

Однако, если вы измените classB.Value to int, этот код будет вызывать упомянутый FatalExecutionEngineError.

Может ли кто-нибудь объяснить, почему или, может быть, на рабочем месте? Я знаю, что это, вероятно, слишком сложно, и я просто возился здесь, но кому-то может понадобиться вызов.

+0

Это * действительно * плохой предмет * все равно *; Наложение ссылок - это ... gah. Почему не просто одно поле «объект» и два свойства, которые используют это поле? Также ... mutable struct, public fields и т. Д. P –

+0

Вы должны использовать только явный макет, если вы точно знаете, что делаете. Он предназначен для неуправляемых сценариев взаимодействия, а не «просто возиться». См. Http://stackoverflow.com/q/23323696/517852. –

+0

Что предназначено для возиться? ^^ ... Я понял, что вы говорите. – CSharpie

ответ

0

В принципе, то, что вы сделали, полностью не определено. Вы обманывая его в двух очень неприятными способами:

  • , делая вид, что одна ссылка не нулевой класс на самом деле другого типа (но это делается без типа-проверки)
  • имея это попытка для загрузки ссылки object (dynamic - это всего лишь object с некоторыми причудливыми трюками компилятора) от int (обратите внимание: во всех случаях это, скорее всего, укажет на мусор, а в случае x64 - даже не на всю ширину, поэтому будет читать мусор в значение разыменования

В принципе: не делаем это. Это, кстати, почему явный макет рассматривается как непроверяемый код. Что же касаюсь, как сделать это «правильно» (и я использую этот термин щедро):

class Magic 
{ 
    private object val; 
    public ClassA InstanceA { get { return (InstanceA)val;} set { val = value; } } 
    public ClassB InstanceB { get { return (InstanceB)val;} set { val = value; } } 
} 

Вы также мог бы использовать val as Foo вместо (Foo)val, если вы хотите увидеть null когда это другой типа.

+0

Ну, я был слишком взволнован здесь с динамическим ключевым словом, я думал, что смогу сделать какой-то «частный доступ». – CSharpie

 Смежные вопросы

  • Нет связанных вопросов^_^