今天就跟大家聊聊有关C#语言中结构体的作用是什么,可能很多人都不太了解,为了让大家更加了解,小编给大家总结了以下内容,希望大家根据这篇文章可以有所收获。
C#语言的结构体是一个比较复杂的东西,在此之上有很多需要设置的参数,否则用起来就很容易出错。下面是msdn上一段描述,看看也许有助于理解C#语言的结构体。
通过使用属性可以自定义结构在内存中的布局方式。例如,可以使用 StructLayout(LayoutKind.Explicit) 和 FieldOffset 属性创建在 C/C++ 中称为联合的布局。
[System.Runtime.InteropServices.StructLayout(LayoutKind.Explicit)] struct TestUnion { [System.Runtime.InteropServices.FieldOffset(0)] public int i; [System.Runtime.InteropServices.FieldOffset(0)] public double d; [System.Runtime.InteropServices.FieldOffset(0)] public char c; [System.Runtime.InteropServices.FieldOffset(0)] public byte b; }
在上一个代码段中,TestUnion 的所有字段都从内存中的同一位置开始。
以下是字段从其他显式设置的位置开始的另一个示例。
[System.Runtime.InteropServices.StructLayout(LayoutKind.Explicit)] struct TestExplicit { [System.Runtime.InteropServices.FieldOffset(0)] public long lg; [System.Runtime.InteropServices.FieldOffset(0)] public int i1; [System.Runtime.InteropServices.FieldOffset(4)] public int i2; [System.Runtime.InteropServices.FieldOffset(8)] public double d; [System.Runtime.InteropServices.FieldOffset(12)] public char c; [System.Runtime.InteropServices.FieldOffset(14)] public byte b; }
i1 和 i2 这两个 int 字段共享与 lg 相同的内存位置。使用平台调用时,这种结构布局控制很有用。
我做了一个简单的测试程序,基本达成预定需求,不过程序该方式要求比较苛刻,如果要解析的数据与转换C#语言的结构体不匹配就会引发一系列莫名其妙的异常(如内存不可读等等之类),下面是测试程序的源代码,有兴趣的朋友可以看一看,也希望网友能提出更好的方案。
using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Text; using System.Windows.Forms; using System.IO; using System.Runtime.InteropServices; namespace RWFile { public partial class Form1 : Form { public Form1() { InitializeComponent(); } //从文件中读结构体 private void button1_Click(object sender, EventArgs e) { string strFile = Application.StartupPath + "\\test.dat"; if (!File.Exists(strFile)) { MessageBox.Show("文件不存在"); return; } FileStream fs = new FileStream(strFile, FileMode.Open, FileAccess.ReadWrite); TestStruct ts = new TestStruct(); byte[] bytData = new byte[Marshal.SizeOf(ts)]; fs.Read(bytData, 0, bytData.Length); fs.Close(); ts = rawDeserialize(bytData); textBox1.Text = ts.dTest.ToString(); textBox2.Text = ts.uTest.ToString(); textBox3.Text = Encoding.Default.GetString(ts.bTest); } //向文件中写结构体 private void button2_Click(object sender, EventArgs e) { string strFile = Application.StartupPath + "\\test.dat"; FileStream fs = new FileStream(strFile, FileMode.Create , FileAccess.Write); TestStruct ts = new TestStruct(); ts.dTest = double.Parse(textBox1.Text); ts.uTest = UInt16.Parse(textBox2.Text); ts.bTest = Encoding.Default.GetBytes(textBox3.Text); byte[] bytData = rawSerialize(ts); fs.Write(bytData, 0, bytData.Length); fs.Close(); } [StructLayout(LayoutKind.Sequential,CharSetCharSet = CharSet.Ansi)] //,Size=16 public struct TestStruct { [MarshalAs(UnmanagedType.R8)] //,FieldOffset(0)] public double dTest; [MarshalAs(UnmanagedType.U2)] //, FieldOffset(8)] public UInt16 uTest; [MarshalAs(UnmanagedType.ByValArray, SizeConst = 6)] //, FieldOffset(10)] public byte[] bTest; } //序列化 public static byte[] rawSerialize(object obj) { int rawsize = Marshal.SizeOf(obj); IntPtr buffer = Marshal.AllocHGlobal(rawsize); Marshal.StructureToPtr(obj, buffer, false); byte[] rawdatas = new byte[rawsize]; Marshal.Copy(buffer, rawdatas, 0, rawsize); Marshal.FreeHGlobal(buffer); return rawdatas; } //反序列化 public static TestStruct rawDeserialize(byte[] rawdatas) { Type anytype = typeof(TestStruct); int rawsize = Marshal.SizeOf(anytype); if (rawsize > rawdatas.Length) return new TestStruct(); IntPtr buffer = Marshal.AllocHGlobal(rawsize); Marshal.Copy(rawdatas, 0, buffer, rawsize); object retobj = Marshal.PtrToStructure(buffer, anytype); Marshal.FreeHGlobal(buffer); return (TestStruct)retobj; } } }
看完上述内容,你们对C#语言中结构体的作用是什么有进一步的了解吗?如果还想了解更多知识或者相关内容,请关注亿速云行业资讯频道,感谢大家的支持。
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。