2013-02-04 39 views
3

我正在修改的一些代碼通過將結構加載到字節數組或從字節數組中進行擴展來廣泛使用結構體與某些工廠設備進行通信。在C#中初始化一個結構體?

這是一個這樣的結構的超簡化示例。

[StructLayout(LayoutKind.Sequential, Pack = 1)] 
public struct K_FOO 
{ 
    public byte a_byte; // 1 byte 
    public BYTE3_TYPE b3; // 3 bytes 
    public int num;  // happens to be 4 bytes 
} 

BYTE3_TYPE看起來像這樣...

[StructLayout(LayoutKind.Sequential, Pack = 1)] 
public class BYTE3_TYPE 
{ 
    [System.Runtime.InteropServices.MarshalAs(UnmanagedType.ByValArray, SizeConst = 3)] 
    public byte[] L = new byte[3]; 
} 

如果我只是做了

K_FOO origFoo = new K_FOO(); 

int和字節被初始化爲0的,我想是因爲他們是原生類型,但是字節數組b3是* un *初始化 - 全爲空。我必須明確地加載它,例如,

BYTE3_TYPE b3 = new BYTE3_TYPE(); 
    origFoo.b3 = b3; 

...我想不出任何可替代的,因爲結構不帶參數構造函數,但真正的結構是巨大的。

但我注意到一些有趣的事情。我們有將這些結構複製到字節數組和從字節數組中複製的例程。例如 。 。 。

public static T ByteArrayToStructure<T>(byte[] buffer) where T : struct 
    { 
     int length = buffer.Length; 
     IntPtr ptr = Marshal.AllocHGlobal(length); // allocate (length) bytes 
     Marshal.Copy(buffer, 0, ptr, length); // copies into UNmanaged space 
     T result = (T)Marshal.PtrToStructure(ptr, typeof(T)); 
     Marshal.FreeHGlobal(ptr); 
     return result; 
    } 

...如果我把它叫做...

K_FOO retFoo = ByteArrayToStructure<K_FOO>(buffer.bytes); 

...所產生的結構返回完全初始化,字節數組中的字節都曾經有過自己的空間分配,使他們可以加載,顯然在PtrToStructure()調用。這意味着.Net「知道」如何初始化這樣的結構。那麼是否有某種方法可以讓.Net爲我做到這一點,這樣我就可以避免編寫數百行顯式初始化代碼?提前致謝!

回答

6

如果您使BYTE3_TYPE爲結構而不是類,則默認構造函數(調用K_FOO origFoo = new K_FOO();)會將整個事件初始化爲零。

如果您嘗試匹配現有規範並將其傳遞到自定義硬件,這也可能是正確的方法。

+1

+1,你也可以看看[固定大小的緩衝](http://msdn.microsoft.com/en-gb/library/zycewsya(v = vs.80).aspx),這意味着字節數組將嵌入到BYTE3_TYPE結構中,而不是生活在堆上。 – MattDavey

+0

難道我不得不設置不安全的做固定?現在我有幾個例程,比如使用不安全代碼的ByteArrayToStructure,但我想保持整個程序「安全」,可以這麼說。 – user316117

+0

@Reed - 我剛剛使用了BYTE3_TYPE作爲一個簡單的例子 - 真正的用戶定義類型比簡單的本地類型數組(比如字節)更復雜。我的問題的真正要義是,因爲.net似乎知道如何初始化這些東西,我有沒有更好的方式來做到這一點,而不是自己明確地做到這一點? – user316117