主要是看默認封送處理行爲函數
按類成員的類型是否爲「可直接傳遞到非託管內存」的類型來分類;按照成員中是否有「可直接傳遞到非託管內存」的類型來討論。spa
全部成員都是「可直接傳遞到非託管內存」的類型指針
託管代碼和非託管代碼:code
//託管代碼 ClassStruct cs = new ClassStruct(); cs.a = 90; cs.d = 23; DoClassStruct(cs); Console.Read(); } [StructLayout(LayoutKind.Sequential)] class ClassStruct { public int a; public double d; } 、、、、、、、、、、、////////////非託管代碼 typedef struct
{
int a;
double d;
}CLASSSTRUCT;
extern "C" __declspec(dllexport) void DoClassStruct(CLASSSTRUCT *cs)
{
printf("%d\n",cs->a);
printf("%lf\n",cs->d);
cs->a=100;
}
下斷點,在DoClassStruct(cs);處,發現cs的地址是0x01bcbaa0;進入 非託管函數中,下斷點,發現cs的地址不變。以下:blog
0x01BCBAA0 5a 00 00 00 00 00 00 00 00 00 00 00 00 00 37 40 Z.............7@ 其中的5a是指90,後面8位是指double值23.0 。內存
結論:若是類的字段都是「可直接傳遞到非託管代碼中」的類型,那麼傳遞是引用,或者說是指針。這是在非託管代碼中的修改也會反映到託管代碼中了。這個過程就是鎖定。string
類的成員不包含「非可直接傳遞到非託管代碼中」的類型it
看下面一個例子,知足條件的類型有bool和string類型等。class
cs.a = 90; cs.d = 23; cs.str = "abcd"; DoClassStruct(cs); Console.WriteLine(cs.a); Console.Read(); } [StructLayout(LayoutKind.Sequential)] class ClassStruct { public int a; public double d; public string str; } /////////////////////////////非託管代碼 typedef struct { int a; double d; char *pStr; }CLASSSTRUCT; extern "C" __declspec(dllexport) void DoClassStruct(CLASSSTRUCT *cs) { printf("%d\n",cs->a); printf("%lf\n",cs->d); cs->a=100; }
經過跟蹤發現,依然使用普通結構體的過程:在非託管內存中開闢空間---把託管內存中數據複製一份到非託管內存M-----內存M的地址做爲參數傳遞給函數---一切的操做都是圍着內存M進行。 可想而知,最後的結果不會反映到託管內存中去。引用