Próbuję zrozumieć, dlaczego drugi przykład poniżej działa bez problemów, ale pierwszy przykład daje mi wyjątek poniżej. Wydaje mi się, że oba przykłady powinny stanowić wyjątek w oparciu o opis. Czy ktoś może mnie oświecić?C# StructLayout.Explicit Question
Nieobsłużone Wyjątek System.TypeLoadException: Nie można typ obciążenia 'StructTest.OuterType' z zestawu 'StructTest, wersja = 1.0.0.0, culture = neutralne TokenKluczaPublicznego = null' ponieważ zawiera pole obiektu pod przesunięcie 0, które jest niepoprawnie wyrównane lub nałożone przez pole nie będące obiektem.
na StructTest.Program.Main (String [] args) Naciśnij dowolny klawisz, aby kontynuować. . .
Przykład 1
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
namespace StructTest
{
[StructLayout(LayoutKind.Sequential, Pack = 1)]
struct InnerType
{
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 100)]
char[] buffer;
}
[StructLayout(LayoutKind.Explicit)]
struct OuterType
{
[FieldOffset(0)]
int someValue;
[FieldOffset(0)]
InnerType someOtherValue;
}
class Program
{
static void Main(string[] args)
{
OuterType t = new OuterType();
System.Console.WriteLine(t);
}
}
}
Przykład 2
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
namespace StructTest
{
[StructLayout(LayoutKind.Sequential, Pack = 1)]
struct InnerType
{
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 100)]
char[] buffer;
}
[StructLayout(LayoutKind.Explicit)]
struct OuterType
{
[FieldOffset(4)]
private int someValue;
[FieldOffset(0)]
InnerType someOtherValue;
}
class Program
{
static void Main(string[] args)
{
OuterType t = new OuterType();
System.Console.WriteLine(t);
}
}
}
Rozumiem, więc jeśli chciałbym zrobić to poprawnie, aby działało poprawnie na maszynach 32- lub 64-bitowych, musiałbym użyć odpowiednio offsetu 8 i 0, prawda? Problem polega na tym, że to, co naprawdę chciałem stworzyć, było związkiem i wygląda na to, że to nie będzie jeden, jeśli nie będę mógł użyć tego samego przesunięcia. –
Tak. Będzie działać na CLR x64 z przesunięciami 8 i 0. Zauważ, że podczas działania fragmentu kodu, jeśli robisz to w rzeczywistej aplikacji, prawdopodobnie łączysz się z pewnymi niezarządzanymi rzeczami, które wymagałyby dokładnych przesunięć. Jeśli ustawisz go na 8, może zawieść na komputerach 32-bitowych (nie ten sam fragment, ale niezarządzany kod, z którym się łączysz). –
Przy okazji, możesz ** może ** mieć zachodzące na siebie pola, jeśli są * niezarządzanego typu *, ale tablica .NET jest typem odniesienia (którego nie można uznać za typ niezarządzany według specyfikacji C#). Więc nie możesz mieć typu referencyjnego jako członka unii w języku C#. Jeśli naprawdę tego potrzebujesz, powinieneś rozważyć użycie takich typów wskaźników jak elementy struktury zamiast tablicy. –