Wat*_*ter 8 c# structlayout c#-10.0
我做需要连续数据的事情。现在使用 C# 10,我们可以执行public readonly record struct.
我喜欢记录所具有的自动 ToString 功能,所以为我完成这个功能真是太好了。
因此,以下等价吗?
[StructLayout(LayoutKind.Sequential, Pack = 4)]
public readonly struct MyVector
{
public readonly float X;
public readonly float Y;
public readonly float Z;
public MyVector(float x, float y, float z)
{
X = x;
Y = y;
Z = z;
}
}
Run Code Online (Sandbox Code Playgroud)
与简洁的 C# 10 版本相比
[StructLayout(LayoutKind.Sequential, Pack = 4)]
public readonly record struct MyVectorRecord(float X, float Y, float Z)
{
}
Run Code Online (Sandbox Code Playgroud)
或者我这样做会不小心踩到任何地雷吗?我的意思是,是否有任何事情在幕后进行,使得record我上面写的内容不能达到我想要的连续包装效果?我不能让记录插入填充、间距或做任何奇怪的事情。
我没有使用带有记录结构的向量类,而是将其用于说明目的。您可以忽略“浮点相等比较”之类的内容,因为我只关心是否可以将其传递给需要 X/Y/Z 连续序列的库。
Pan*_*vos 13
record不是新类型,它是应用于引用类型和现在值类型的特定行为。该结构仍然是一个结构。您可以在Sharplab.io上对此进行测试,以查看编译器在每种情况下生成的代码。
不过,记录使用属性,而不是原始字段,因此您只能将结构与属性进行比较来记录结构。这就是重要的区别
这个结构:
[StructLayout(LayoutKind.Sequential, Pack = 4)]
public readonly struct MyVectorRecord2
{
public float X {get;}
public float Y {get;}
public float Z {get;}
public MyVectorRecord2(float x, float y, float z)
{
X = x;
Y = y;
Z = z;
}
}
Run Code Online (Sandbox Code Playgroud)
产生
[StructLayout(LayoutKind.Sequential, Pack = 4)]
[IsReadOnly]
public struct MyVectorRecord2
{
[CompilerGenerated]
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
private readonly float <X>k__BackingField;
[CompilerGenerated]
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
private readonly float <Y>k__BackingField;
[CompilerGenerated]
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
private readonly float <Z>k__BackingField;
public float X
{
[CompilerGenerated]
get
{
return <X>k__BackingField;
}
}
public float Y
{
[CompilerGenerated]
get
{
return <Y>k__BackingField;
}
}
public float Z
{
[CompilerGenerated]
get
{
return <Z>k__BackingField;
}
}
public MyVectorRecord2(float x, float y, float z)
{
<X>k__BackingField = x;
<Y>k__BackingField = y;
<Z>k__BackingField = z;
}
}
Run Code Online (Sandbox Code Playgroud)
记录的同时
[StructLayout(LayoutKind.Sequential, Pack = 4)]
public readonly record struct MyVectorRecord(float X, float Y, float Z)
{
}
Run Code Online (Sandbox Code Playgroud)
产生:
[StructLayout(LayoutKind.Sequential, Pack = 4)]
[IsReadOnly]
public struct MyVectorRecord : IEquatable<MyVectorRecord>
{
[CompilerGenerated]
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
private readonly float <X>k__BackingField;
[CompilerGenerated]
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
private readonly float <Y>k__BackingField;
[CompilerGenerated]
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
private readonly float <Z>k__BackingField;
public float X
{
[CompilerGenerated]
get
{
return <X>k__BackingField;
}
[CompilerGenerated]
init
{
<X>k__BackingField = value;
}
}
public float Y
{
[CompilerGenerated]
get
{
return <Y>k__BackingField;
}
[CompilerGenerated]
init
{
<Y>k__BackingField = value;
}
}
public float Z
{
[CompilerGenerated]
get
{
return <Z>k__BackingField;
}
[CompilerGenerated]
init
{
<Z>k__BackingField = value;
}
}
public MyVectorRecord(float X, float Y, float Z)
{
<X>k__BackingField = X;
<Y>k__BackingField = Y;
<Z>k__BackingField = Z;
}
public override string ToString()
{
StringBuilder stringBuilder = new StringBuilder();
stringBuilder.Append("MyVectorRecord");
stringBuilder.Append(" { ");
if (PrintMembers(stringBuilder))
{
stringBuilder.Append(' ');
}
stringBuilder.Append('}');
return stringBuilder.ToString();
}
private bool PrintMembers(StringBuilder builder)
{
builder.Append("X = ");
builder.Append(X.ToString());
builder.Append(", Y = ");
builder.Append(Y.ToString());
builder.Append(", Z = ");
builder.Append(Z.ToString());
return true;
}
public static bool operator !=(MyVectorRecord left, MyVectorRecord right)
{
return !(left == right);
}
public static bool operator ==(MyVectorRecord left, MyVectorRecord right)
{
return left.Equals(right);
}
public override int GetHashCode()
{
return (EqualityComparer<float>.Default.GetHashCode(<X>k__BackingField) * -1521134295 + EqualityComparer<float>.Default.GetHashCode(<Y>k__BackingField)) * -1521134295 + EqualityComparer<float>.Default.GetHashCode(<Z>k__BackingField);
}
public override bool Equals(object obj)
{
return obj is MyVectorRecord && Equals((MyVectorRecord)obj);
}
public bool Equals(MyVectorRecord other)
{
return EqualityComparer<float>.Default.Equals(<X>k__BackingField, other.<X>k__BackingField) && EqualityComparer<float>.Default.Equals(<Y>k__BackingField, other.<Y>k__BackingField) && EqualityComparer<float>.Default.Equals(<Z>k__BackingField, other.<Z>k__BackingField);
}
public void Deconstruct(out float X, out float Y, out float Z)
{
X = this.X;
Y = this.Y;
Z = this.Z;
}
}
Run Code Online (Sandbox Code Playgroud)
最后,这个
[StructLayout(LayoutKind.Sequential, Pack = 4)]
public readonly struct MyVector
{
public readonly float X;
public readonly float Y;
public readonly float Z;
public MyVector(float x, float y, float z)
{
X = x;
Y = y;
Z = z;
}
}
Run Code Online (Sandbox Code Playgroud)
除属性外,保持不变IsReadOnly。
[StructLayout(LayoutKind.Sequential, Pack = 4)]
[IsReadOnly]
public struct MyVector
{
public readonly float X;
public readonly float Y;
public readonly float Z;
public MyVector(float x, float y, float z)
{
X = x;
Y = y;
Z = z;
}
}
Run Code Online (Sandbox Code Playgroud)
最大的区别在于具有字段的结构和具有公共属性的结构之间。之后,record struct与具有属性的结构相比,a 仅包含额外的方法。