100 likes | 113 Views
Union in C#. 劉崇汎 崑山科技大學 電腦與通訊系 http://www.ksu.edu.tw. 前言. 在一般市面上的工具書中,都沒有介紹到如何在 C# 程式中使用 Union 。 缺乏 Union 將使得在很多應用 ( 如 Driver 的撰寫 ) 無法有效地做資料轉換。. 使用 Union 的步驟. 新增一個 C# 類別 專案選單,選擇新增類別 引用 System.Runtime.InteropServices; 在新類別程式碼最前方, using System.Runtime.InteropServices; 宣告要用 StructLayout
E N D
Union in C# 劉崇汎 崑山科技大學 電腦與通訊系 http://www.ksu.edu.tw
前言 • 在一般市面上的工具書中,都沒有介紹到如何在C#程式中使用Union。 • 缺乏Union將使得在很多應用(如Driver的撰寫)無法有效地做資料轉換。
使用Union的步驟 • 新增一個C#類別 • 專案選單,選擇新增類別 • 引用 System.Runtime.InteropServices; • 在新類別程式碼最前方,using System.Runtime.InteropServices; • 宣告要用StructLayout • 就是在類別的class宣告前加入一行[StructLayout(LayoutKind.Explicit)] • 用[FieldOffset(n)]指定每一個變數的位置。 • 也就是在每一個變數前加入一行[FieldOffset(n)] • 其中n就是以byte為單位的偏移值。第一個起始位置是 0。
程式碼 [FieldOffset(2)] public byte byte3; [FieldOffset(3)] public byte byte4; [FieldOffset(0)] public int myInt0; [FieldOffset(2)] public int myInt2; } } using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Runtime.InteropServices; namespace UnionTest { [StructLayout(LayoutKind.Explicit)] public class MyUnionClass { [FieldOffset(0)] public byte byte1; [FieldOffset(1)] public byte byte2;
Form程式碼 using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Windows.Forms; namespace UnionTest { public partial class Form1 : Form { MyUnionClass myUnion = new MyUnionClass(); public Form1() { InitializeComponent(); } private void button1_Click(object sender, EventArgs e) { myUnion.byte1 = System.Convert.ToByte(textBox1.Text); textBox5.Text = myUnion.myInt0.ToString(); textBox6.Text = myUnion.myInt2.ToString(); } private void button2_Click(object sender, EventArgs e) { myUnion.byte2 = System.Convert.ToByte(textBox2.Text); textBox5.Text = myUnion.myInt0.ToString(); textBox6.Text = myUnion.myInt2.ToString(); }
Form程式碼 private void button3_Click(object sender, EventArgs e) { myUnion.byte3 = System.Convert.ToByte(textBox3.Text); textBox5.Text = myUnion.myInt0.ToString(); textBox6.Text = myUnion.myInt2.ToString(); } private void button4_Click(object sender, EventArgs e) { myUnion.byte4 = System.Convert.ToByte(textBox4.Text); textBox5.Text = myUnion.myInt0.ToString(); textBox6.Text = myUnion.myInt2.ToString(); } private void button5_Click(object sender, EventArgs e) { myUnion.myInt0 = System.Convert.ToInt32(textBox5.Text); textBox1.Text = myUnion.byte1.ToString(); textBox2.Text = myUnion.byte2.ToString(); textBox3.Text = myUnion.byte3.ToString(); textBox4.Text = myUnion.byte4.ToString(); textBox6.Text = myUnion.myInt2.ToString(); } private void button6_Click(object sender, EventArgs e) { myUnion.myInt2 = System.Convert.ToInt32(textBox6.Text); textBox1.Text = myUnion.byte1.ToString(); textBox2.Text = myUnion.byte2.ToString(); textBox3.Text = myUnion.byte3.ToString(); textBox4.Text = myUnion.byte4.ToString(); textBox5.Text = myUnion.myInt0.ToString(); } } }
注意事項 • 注意Offset的值,出錯會很嚴重。 • Int現在都是32bits • 沒有比byte小的方式,需要用的時候請用mask去做and/ or 動作解決。 • 用物件導向寫法的 {set; get;}很簡潔好用。 (下頁) • 類似需要兩三個bit的欄位可以參考這個寫法。
Bit Level的Union [FieldOffset(0)] private byte bit01; public byte Bit01 { set { if (value == 1) bit01 = (byte)(bit01 | 0x01); if (value == 0) bit01 = (byte)(bit01 & 0xFE); } get { return (byte)(bit01 & 0x01); } } } } using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Runtime.InteropServices; namespace UnionTest { [StructLayout(LayoutKind.Explicit)] public class MyUnionClass { [FieldOffset(0)] public byte byte1; [FieldOffset(1)] public byte byte2; …………………………. …………………….