{
public int id;
public string s;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 6)]
public int[] test;
}
在c#中struct里面定义数组,为什么要加类似 [MarshalAs(UnmanagedType.ByValArray, SizeConst = 6)] 这行东西呢。
看资料说因为struct是值类型,而数组是引用类型,所以出现这些麻烦。
不过,string不也是引用类型吗,为什么用起来又没啥特别?
9 个解决方案
#1
另外网上找到用unsafe的写法
public unsafe fixed int test[6];
这个和
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 6)]
public int[] test;
的写法,两者的比较是怎样的?
请大家指点~~
public unsafe fixed int test[6];
这个和
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 6)]
public int[] test;
的写法,两者的比较是怎样的?
请大家指点~~
#2
结构里使用数组不需要你定义[MarshalAs(UnmanagedType.ByValArray, SizeConst = 6)],我给个例子给你看看:
class Program
{
static void Main(string[] args)
{
StructTest structTest = new StructTest();
structTest.PointX = 20;
structTest.PointY = 30;
structTest.SizePoint = new int[] { 3, 6, 27, 48 };
Console.WriteLine("PointX = {0}, PointY = {1}", structTest.PointX, structTest.PointY);
Console.WriteLine("SizePoint array has {0} element, Now output:\r", structTest.SizePoint.Length);
foreach (int x in structTest.SizePoint)
{
Console.WriteLine(x.ToString());
}
Console.ReadLine();
}
}
struct StructTest
{
public int PointX;
public int PointY;
public int[] SizePoint;
}
#3
你再看看MSDN里结构的描述,也没有说不能用数组的:
结构是使用 struct 关键字定义的,例如:
public struct PostalAddress
{
// Fields, properties, methods and events go here...
}
public struct PostalAddress
{
// Fields, properties, methods and events go here...
}
结构与类共享大多数相同的语法,但结构比类受到的限制更多:
在结构声明中,除非字段被声明为 const 或 static,否则无法初始化。
结构不能声明默认构造函数(没有参数的构造函数)或析构函数。
结构在赋值时进行复制。将结构赋值给新变量时,将复制所有数据,并且对新副本所做的任何修改不会更改原始副本的数据。在使用值类型的集合(如 Dictionary<string, myStruct>)时,请务必记住这一点。
结构是值类型,而类是引用类型。
与类不同,结构的实例化可以不使用 new 运算符。
结构可以声明带参数的构造函数。
一个结构不能从另一个结构或类继承,而且不能作为一个类的基。所有结构都直接继承自 System.ValueType,后者继承自 System.Object。
结构可以实现接口。
结构可用作可以为 null 的类型,因而可向其赋 null 值。
结构是使用 struct 关键字定义的,例如:
public struct PostalAddress
{
// Fields, properties, methods and events go here...
}
public struct PostalAddress
{
// Fields, properties, methods and events go here...
}
结构与类共享大多数相同的语法,但结构比类受到的限制更多:
在结构声明中,除非字段被声明为 const 或 static,否则无法初始化。
结构不能声明默认构造函数(没有参数的构造函数)或析构函数。
结构在赋值时进行复制。将结构赋值给新变量时,将复制所有数据,并且对新副本所做的任何修改不会更改原始副本的数据。在使用值类型的集合(如 Dictionary<string, myStruct>)时,请务必记住这一点。
结构是值类型,而类是引用类型。
与类不同,结构的实例化可以不使用 new 运算符。
结构可以声明带参数的构造函数。
一个结构不能从另一个结构或类继承,而且不能作为一个类的基。所有结构都直接继承自 System.ValueType,后者继承自 System.Object。
结构可以实现接口。
结构可用作可以为 null 的类型,因而可向其赋 null 值。
#4
但是如果要在struct里面指定数组大小,就只能按前面的方法做吧
#5
// 如果要定义的时候指定大小,为什么不直接new呢?
public struct sTest
{
public int id;
public string s;
public int[] test = new int[6] { 0 };
}
#6
这是调用非托管程序的需要
#7
其实,char str[128];这种C/C++的风格,映射到C#时,也要指定数组长度大小!
而char* str,因为是字符指针,是变长的,在结构体只占4个字节,string是引用类,也是4个字节,刚好对齐。
要解释数组为什么一定要指定大小,你可以从C++角度去想:
int ary[2];
如果换成是C#:
int[2] ary;
你编译一下,编译器马上报错!
由于两边的编译器不一样,产生两边的语法不一样,这是很正常的!
不知道这样解释你清楚没有?
而char* str,因为是字符指针,是变长的,在结构体只占4个字节,string是引用类,也是4个字节,刚好对齐。
要解释数组为什么一定要指定大小,你可以从C++角度去想:
int ary[2];
如果换成是C#:
int[2] ary;
你编译一下,编译器马上报错!
由于两边的编译器不一样,产生两边的语法不一样,这是很正常的!
不知道这样解释你清楚没有?
#8
+
#9
去学VB.NET吧,据说VB.NET中简单多了,根本不需要注明这么多,它都是智能感知的。(我认为很不严谨)
你这边和引用类型无关,如果不需要传递给C++这类非托管dll调用,就根本不需要添加MarshalAs的声明,那个是将对象地址固定用的,不然动态的地址是无法传递给非托管dll调用的。
你这边和引用类型无关,如果不需要传递给C++这类非托管dll调用,就根本不需要添加MarshalAs的声明,那个是将对象地址固定用的,不然动态的地址是无法传递给非托管dll调用的。
#1
另外网上找到用unsafe的写法
public unsafe fixed int test[6];
这个和
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 6)]
public int[] test;
的写法,两者的比较是怎样的?
请大家指点~~
public unsafe fixed int test[6];
这个和
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 6)]
public int[] test;
的写法,两者的比较是怎样的?
请大家指点~~
#2
结构里使用数组不需要你定义[MarshalAs(UnmanagedType.ByValArray, SizeConst = 6)],我给个例子给你看看:
class Program
{
static void Main(string[] args)
{
StructTest structTest = new StructTest();
structTest.PointX = 20;
structTest.PointY = 30;
structTest.SizePoint = new int[] { 3, 6, 27, 48 };
Console.WriteLine("PointX = {0}, PointY = {1}", structTest.PointX, structTest.PointY);
Console.WriteLine("SizePoint array has {0} element, Now output:\r", structTest.SizePoint.Length);
foreach (int x in structTest.SizePoint)
{
Console.WriteLine(x.ToString());
}
Console.ReadLine();
}
}
struct StructTest
{
public int PointX;
public int PointY;
public int[] SizePoint;
}
#3
你再看看MSDN里结构的描述,也没有说不能用数组的:
结构是使用 struct 关键字定义的,例如:
public struct PostalAddress
{
// Fields, properties, methods and events go here...
}
public struct PostalAddress
{
// Fields, properties, methods and events go here...
}
结构与类共享大多数相同的语法,但结构比类受到的限制更多:
在结构声明中,除非字段被声明为 const 或 static,否则无法初始化。
结构不能声明默认构造函数(没有参数的构造函数)或析构函数。
结构在赋值时进行复制。将结构赋值给新变量时,将复制所有数据,并且对新副本所做的任何修改不会更改原始副本的数据。在使用值类型的集合(如 Dictionary<string, myStruct>)时,请务必记住这一点。
结构是值类型,而类是引用类型。
与类不同,结构的实例化可以不使用 new 运算符。
结构可以声明带参数的构造函数。
一个结构不能从另一个结构或类继承,而且不能作为一个类的基。所有结构都直接继承自 System.ValueType,后者继承自 System.Object。
结构可以实现接口。
结构可用作可以为 null 的类型,因而可向其赋 null 值。
结构是使用 struct 关键字定义的,例如:
public struct PostalAddress
{
// Fields, properties, methods and events go here...
}
public struct PostalAddress
{
// Fields, properties, methods and events go here...
}
结构与类共享大多数相同的语法,但结构比类受到的限制更多:
在结构声明中,除非字段被声明为 const 或 static,否则无法初始化。
结构不能声明默认构造函数(没有参数的构造函数)或析构函数。
结构在赋值时进行复制。将结构赋值给新变量时,将复制所有数据,并且对新副本所做的任何修改不会更改原始副本的数据。在使用值类型的集合(如 Dictionary<string, myStruct>)时,请务必记住这一点。
结构是值类型,而类是引用类型。
与类不同,结构的实例化可以不使用 new 运算符。
结构可以声明带参数的构造函数。
一个结构不能从另一个结构或类继承,而且不能作为一个类的基。所有结构都直接继承自 System.ValueType,后者继承自 System.Object。
结构可以实现接口。
结构可用作可以为 null 的类型,因而可向其赋 null 值。
#4
但是如果要在struct里面指定数组大小,就只能按前面的方法做吧
#5
// 如果要定义的时候指定大小,为什么不直接new呢?
public struct sTest
{
public int id;
public string s;
public int[] test = new int[6] { 0 };
}
#6
这是调用非托管程序的需要
#7
其实,char str[128];这种C/C++的风格,映射到C#时,也要指定数组长度大小!
而char* str,因为是字符指针,是变长的,在结构体只占4个字节,string是引用类,也是4个字节,刚好对齐。
要解释数组为什么一定要指定大小,你可以从C++角度去想:
int ary[2];
如果换成是C#:
int[2] ary;
你编译一下,编译器马上报错!
由于两边的编译器不一样,产生两边的语法不一样,这是很正常的!
不知道这样解释你清楚没有?
而char* str,因为是字符指针,是变长的,在结构体只占4个字节,string是引用类,也是4个字节,刚好对齐。
要解释数组为什么一定要指定大小,你可以从C++角度去想:
int ary[2];
如果换成是C#:
int[2] ary;
你编译一下,编译器马上报错!
由于两边的编译器不一样,产生两边的语法不一样,这是很正常的!
不知道这样解释你清楚没有?
#8
+
#9
去学VB.NET吧,据说VB.NET中简单多了,根本不需要注明这么多,它都是智能感知的。(我认为很不严谨)
你这边和引用类型无关,如果不需要传递给C++这类非托管dll调用,就根本不需要添加MarshalAs的声明,那个是将对象地址固定用的,不然动态的地址是无法传递给非托管dll调用的。
你这边和引用类型无关,如果不需要传递给C++这类非托管dll调用,就根本不需要添加MarshalAs的声明,那个是将对象地址固定用的,不然动态的地址是无法传递给非托管dll调用的。