2013-10-25 42 views
3

用於一結構的字節數組構件我具有這樣的結構定義如下:創建在C#

public struct check 
{ 
    public int[] x = new int[3]; //error 
} 

這是一個錯誤,因爲你不能在C#的結構部件限定的陣列大小。我不能爲C#中的默認構造函數定義此數組的空間,因爲不允許使用無參數的構造函數。

我該怎麼做?我知道C#中的結構是不可變的。

我使用這個結構不是爲了創建新的對象,而是爲了對其他類類型進行類型轉換。

check corp = (check)WmUtils.WM_GetObj(Attr); 

Wm_getObj返回check2類型的對象。 Readonly關鍵字在這裏有幫助嗎?

+0

結構在C#中不是天生不變的。讓它們變得可變是一個非常糟糕的主意,因爲它可能導致各種各樣的問題。 –

回答

2

你不能有一個參數的構造函數,你不能定義與結構大小的數組,這個給你留下一個結構構造採取size像參數:

public struct check 
{ 
    public int[] x; 
    public check(int size) 
    { 
     x = new int[size]; 
    } 
} 
+0

這確實有效,但我不想在創建對象時傳遞大小,因爲大小總是固定爲3. –

+0

如果大小總是3,爲什麼不創建3個int變量? –

+0

如果尺寸是100? –

1

給出一個CHECK2類:

public class check2 
    { 
    public int x1 { get; set; } 
    public int x2 { get; set; } 
    public int x3 { get; set; } 
    } 

在你的帶有整型數組的結構中,只需添加一個運算符來從類中轉換它。操作員可以初始化從類實例的數組:

public struct check 
    { 
    public int[] x; 

    public static explicit operator check(check2 c2) 
    { 
     return new check() { x = new int[3] { c2.x1, c2.x2, c2.x3 } }; 
    } 
    } 

現在,您可以創建一個check2類,並將其轉換爲check結構:

check2 c2 = new check2() { x1 = 1, x2 = 2, x3 = 3 }; 
    check s = (check)c2; 
    Console.WriteLine(string.Format("{0}, {1}, {2}", s.x[0], s.x[1], s.x[2])); 

此輸出1, 2, 3

+0

其實它並不總是check2型的,有時候其他的結構也是 –

+0

你需要爲它們中的每一個定義一個運算符。它們之間可能有一些共享的代碼,但最終每個轉換都必須定義。 – jltrem

1

怎麼樣fixed array buffer

public unsafe struct Buffer 
{ 
    const int Size=100; 
    fixed byte data[Size]; 

    public void Clear() 
    { 
     fixed(byte* ptr=data) 
     { 
      // Fill values with 0 
      for(int i=0; i<Size; i++) 
      { 
       ptr[i]=0; 
      } 
     } 
    } 

    public void Store(byte[] array, int index) 
    { 
     fixed(byte* ptr=data) 
     { 
      // find max elements remaining 
      int N=Math.Min(index + array.Length, Size) - index; 
      // Fill values from input bytes 
      for(int i=0; i<N; i++) 
      { 
       ptr[index+i]=array[i]; 
      } 
     } 
    } 

    public byte[] ToArray() 
    { 
     byte[] array=new byte[Size]; 
     fixed(byte* ptr=data) 
     { 
      // Extract all data 
      for(int i=0; i<Size; i++) 
      { 
       array[i]=ptr[i]; 
      } 
     } 
     return array; 
    } 
} 

unsafe class Program 
{ 
    static void Main(string[] args) 
    { 
     Buffer buffer=new Buffer(); 
     // buffer contains 100 bytes 
     int size=sizeof(Buffer); 
     // size = 100 
     buffer.Clear(); 
     // data = { 0, 0, 0, ... } 
     buffer.Store(new byte[] { 128, 207, 16, 34 }, 0); 

     byte[] data=buffer.ToArray(); 
     // { 128, 207, 16, 34, 0, 0, ... } 
    } 
} 

(PS需要用編譯允許不安全代碼

+0

我討厭不安全。對不起 –

+1

它吠叫不止它咬。當正確完成時,它是完全安全的。只是保持簡單。我**憎恨**他們使用_unsafe_這樣的詞應該是_legacy_或_allow指針_。 – ja72

+0

你是對的!其實我的心理障礙與它的內涵 –

0

使用類而不是結構。

+0

明智的答案。在Tyler Durden,我們相信! –

+0

但是如果你想演員,你仍然需要定義操作員! – jltrem

2

如何:

struct Check 
{ 
    private int[] _x ; 
    public int[] X { get { return _x ?? new int[3]{0,0,0,} ; } } 
} 

,直到它被引用這會延遲內部數組的實例。假設陣列參考在實例的整個生命週期內保持不變,所以您確實不需要set訪問器。這裏唯一的缺點是由於第一次引用屬性X時隱含競爭條件,所以這不是線程安全的。然而,由於你的結構假定存在於堆棧中,所以這可能不是一個大問題。

0

這可能會有很大的幫助。我創建了結構MyX, Struct包含方法ToByte和Struct 因此,如果您有字節數組,您可以用字節 填充您的結構數組但是請確保您的字節數組對齊正確。 希望這有助於。

public struct MyX 
    { 
     public int IntValue; 
     [MarshalAs(UnmanagedType.ByValArray, SizeConst = 3, ArraySubType = UnmanagedType.U1)] 
     public byte[] Array; 

     MyX(int i, int b) 
     { 
      IntValue = b; 
      Array = new byte[3]; 
     } 

     public MyX ToStruct(byte []ar) 
     { 

      byte[] data = ar;//= { 1, 0, 0, 0, 9, 8, 7 }; // IntValue = 1, Array = {9,8,7} 
      IntPtr ptPoit = Marshal.AllocHGlobal(data.Length); 
      Marshal.Copy(data, 0, ptPoit, data.Length); 

      MyX x = (MyX)Marshal.PtrToStructure(ptPoit, typeof(MyX)); 
      Marshal.FreeHGlobal(ptPoit); 

      return x; 
     } 
     public byte[] ToBytes() 
     { 
      Byte[] bytes = new Byte[Marshal.SizeOf(typeof(MyX))]; 
      GCHandle pinStructure = GCHandle.Alloc(this, GCHandleType.Pinned); 
      try 
      { 
       Marshal.Copy(pinStructure.AddrOfPinnedObject(), bytes, 0, bytes.Length); 
       return bytes; 
      } 
      finally 
      { 
       pinStructure.Free(); 
      } 
     } 
    } 

    void function() 
    { 
     byte[] data = { 1, 0, 0, 0, 9, 8, 7 }; // IntValue = 1, Array = {9,8,7} 
     IntPtr ptPoit = Marshal.AllocHGlobal(data.Length); 
     Marshal.Copy(data, 0, ptPoit, data.Length); 

     var x = (MyX)Marshal.PtrToStructure(ptPoit, typeof(MyX)); 
     Marshal.FreeHGlobal(ptPoit); 

     var MYstruc = x.ToStruct(data); 


     Console.WriteLine("x.IntValue = {0}", x.IntValue); 
     Console.WriteLine("x.Array = ({0}, {1}, {2})", x.Array[0], x.Array[1], x.Array[2]); 
    }