错误CS1663是否有任何解决方法("固定大小缓冲区类型必须是以下之一:bool,byte,short,int,long,char,sbyte,ushort,uint,ulong,float或double "?)
我需要从另一个blittable自定义类型结构声明一个不安全的固定数组,但是我遇到了这个编译错误。
显示一些代码以阐明下面的问题。
struct s1
{
byte _b1;
byte _b2;
}
unsafe struct s2
{
fixed s1 _s1[5]; // CS1663 here...
}
请注意,这两个结构是blittable,因此错误对我没有任何意义。
任何人都知道我能做些什么?
感谢。
答案 0 :(得分:1)
这是fixed size buffers的限制。
固定数组可以采用任何属性或修饰符 允许常规struct成员。唯一的限制是 数组类型必须为 bool , byte , char , short , int , 长, sbyte , ushort , uint , ulong , float < / strong>,或加倍。
您只能使用这些类型而不能使用组合(例如struct
只包含那些类型)。如果您的类型是否可用,则没有区别。你就是不能用它。
然后,您无法将自定义struct
用于固定大小的缓冲区。
解决方法?嗯,是的,可能是。您可以更改代码结构并使用以下内容:
unsafe struct s2
{
fixed byte _b1[5];
fixed byte _b2[5];
}
答案 1 :(得分:0)
另一种解决方法是使用指针类型字段。
public struct Foo
{
public byte _b1;
public byte _b2;
}
public unsafe struct Bar
{
public int Length;
public unsafe Foo* Data;
}
或者,如果你的意图是创建一个包含所有自己的数据的单值类型对象,连续(即,它可以在非托管代码中记忆) - 那么唯一的方法是通过根本不使用任何数组。
public struct Foo
{
public byte _b1;
public byte _b2;
}
public struct Bar1
{
public Foo F1;
}
public struct Bar2
{
public Foo F1;
public Foo F2;
}
public struct Bar3
{
public Foo F1;
public Foo F2;
public Foo F3;
}
答案 2 :(得分:0)
我将如何处理您的示例以及类似的复杂性示例,首先要问自己是否可以将结构简化为单个原始类型。如果可以的话,我只能通过属性或索引器访问将固定缓冲区隐藏在结构内部。
在您的示例中,您具有以下内容。
struct s1
{
byte _b1;
byte _b2;
}
unsafe struct s2
{
fixed s1 _s1[5]; // CS1663 here...
}
如果我决定绝对需要将结构排列在单个连续的数据块中,我可能会考虑的事情是这样的。
[StructLayout(LayoutKind.Explicit, Size = 2)]
struct s1
{ // Field offsets to emulate union style access which makes it
// simple to get at the raw data in a primitive type format.
[FieldOffset(0)]ushort _u1;
[FieldOffset(0)]byte _b1;
[FieldOffset(1)]byte _b2;
public s1(ushort data)
{
_b1 = 0;
_b2 = 0;
_u1 = data;
}
public ushort ToUShort()
{
return _u1;
}
}
unsafe struct s2
{
public const int Size = 5;
private fixed ushort _s1[Size];
public s1 this[int index]
{ // A public indexer that provides the data in a friendlier format.
get
{
if (index < 0 || index >= Size )
throw new IndexOutOfRangeException();
return new s1(_s1[index]);
}
set
{
if (index < 0 || index >= Size)
throw new IndexOutOfRangeException();
_s1[index] = value.ToUShort();
}
}
}
如果这看起来像是骇客,那是因为还可以。我不建议将此方法作为一般解决方案,因为它很难维护,但是在少数情况下,您需要以较低的水平进行工作,并且事先知道数据规格不会发生变化,因此需要使用这种技术可行。但是,即使在那种情况下,我仍然更愿意封装尽可能多的低级内容,以最大程度地减少出现问题的可能性。就是说,确实确实按照要求进行操作,这是一种解决方法,可以有固定大小的自定义结构缓冲区。
答案 3 :(得分:0)
[StructLayout(LayoutKind.Sequential)]
public struct S1
{
[MarshalAs(UnmanagedType.I1)] public byte _b1;
[MarshalAs(UnmanagedType.I1)] public byte _b2;
public S1(ushort _ushort)
{
this = new Converter(_ushort).s1;
}
public ushort USHORT() //for fixed arrays
{
return new Converter(this).USHORT;
}
[StructLayout(LayoutKind.Explicit)]
private struct Converter
{
[FieldOffset(0)] public S1 s1;
[FieldOffset(0)] public ushort USHORT;
public Converter(S1 _s1)
{
USHORT = 0;
s1 = _s1;
}
public Converter(ushort _USHORT)
{
s1 = default;
USHORT = _USHORT;
}
}
}
public unsafe struct S2
{
public fixed ushort s1[5];
public S1 this[int n] {
get => new S1(s1[n]); //copy!
set => s1[n] = value.USHORT();
}
}