gpt4 book ai didi

c# - C#10 的只读记录结构是否保证与显式实现相同的字段大小和对齐方式?

转载 作者:行者123 更新时间:2023-12-04 14:48:08 25 4
gpt4 key购买 nike

我做需要连续数据的事情。现在使用 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;
}
}
与精炼的 C# 10 版本相比
[StructLayout(LayoutKind.Sequential, Pack = 4)]
public readonly record struct MyVectorRecord(float X, float Y, float Z)
{
}
或者我会不小心踩到地雷吗?我的意思是, record 在幕后做了什么事情|这使得我上面写的内容在连续包装方面没有做我想做的事?我不能让记录插入填充、间距或做任何奇怪的事情。
我没有使用带有记录结构的向量类,而是出于说明目的使用它。您可以忽略诸如“浮点相等比较”之类的内容,因为我只对是否可以将其传递给期望 X/Y/Z 连续序列的库感兴趣。

最佳答案

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;
}
}
产生
[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;
}
}
虽然记录
[StructLayout(LayoutKind.Sequential, Pack = 4)]
public readonly record struct MyVectorRecord(float X, float Y, float Z)
{
}
产生:
[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;
}
}
最后,这
[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;
}
}
保持不变,除了 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;
}
}
最大的区别在于具有字段的结构和具有公共(public)属性的结构。之后,一个 record struct与具有属性的结构相比,仅包含额外的方法。

关于c# - C#10 的只读记录结构是否保证与显式实现相同的字段大小和对齐方式?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/69607592/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com