【问题标题】:Are record structs passed by value or by reference and can they be blittable or not记录结构是按值传递还是按引用传递,它们是否可写入
【发布时间】:2023-02-02 20:15:25
【问题描述】:

使用大量结构以及数组和结构列表时,在将结构传递给方法或以不同方式使用它们时,通常会遇到减少所述结构副本数量的障碍,这让我很恼火。

此外,我不得不使用结构,因为我需要使用 blittable 类型。

我也知道 ErrorProne.NET 之类的东西,它有很大帮助,但我仍然不满意我目前拥有的解决方案。

现在,有了最新的 C# 和 .NET 版本,我们有了记录类型,它可以同时应用于结构和类,也可以独立使用,但我找不到任何关于传递时复制行为和类似内容的明确信息,关于记录结构与普通结构相比的行为方式以及记录结构是否可以 blittable。

按照我正在谈论的结构示例(此处记录结构)。在最佳情况下,我什至想将它们与自定义对象池结合使用,这样我就可以重新使用它们,而我的程序不必一次又一次地为这些新结构分配内存,同时对旧的未使用的结构进行 GC。


[StructLayout(LayoutKind.Sequential)]
public record struct PagedSecondaryIndexKey
{
    [MarshalAs(UnmanagedType.U1)]
    public SecondaryIndexType IndexType;

    [MarshalAs(UnmanagedType.U8)]
    public ulong Page;
    
    [MarshalAs(UnmanagedType.Struct)]
    public IndexIdentifier IndexIdentifier;
    
    public PagedSecondaryIndexKey(ulong page, SecondaryIndexType indexType, ulong identifier1, ulong identifier2, ulong identifier3)
    {
        IndexType = indexType;
        Page = page;
        IndexIdentifier.Reset(identifier1, identifier2, identifier3);
    }

}

[StructLayout(LayoutKind.Sequential)]
public record struct IndexIdentifier
{
    [MarshalAs(UnmanagedType.U8)]
    private ulong IndexIdentifier1;

    [MarshalAs(UnmanagedType.U8)]
    private ulong IndexIdentifier2;
    
    [MarshalAs(UnmanagedType.U8)]
    private ulong IndexIdentifier3;
    
    public const int Size = 3 * sizeof(ulong);
    
    public IndexIdentifier(ulong identifier1, ulong identifier2, ulong identifier3)
    {
        IndexIdentifier1 = identifier1;
        IndexIdentifier2 = identifier2;
        IndexIdentifier3 = identifier3;
    }
    
    public IndexIdentifier(IndexIdentifier indexKeyIndexIdentifier)
    {
        indexKeyIndexIdentifier.IndexIdentifier1 = IndexIdentifier1;
        indexKeyIndexIdentifier.IndexIdentifier2 = IndexIdentifier2;
        indexKeyIndexIdentifier.IndexIdentifier3 = IndexIdentifier3;
    }

}

尝试了多种方法来解决所提到的问题,使用了多种工具,进行了大量研究,但仍未找到我正在寻找的答案。

【问题讨论】:

  • record struct PagedSecondaryIndexKey基本上是struct PagedSecondaryIndexKey:IEquatable<PagedSecondaryIndexKey>加上一个ToString()。您可以将它们放入sharplab.io,并查看编译后的代码。

标签: c# struct record .net-7.0


【解决方案1】:

基本上,记录只是向类添加一些默认方法(ToString、Equals 等),但 record class 表现得像一个类(它是一个引用类型),而 record struct 表现得像一个结构(它是一个值类型) ).

这也意味着当且仅当等效结构是 blittable 时,记录结构是 blittable 的。这基本上意味着结构/记录结构不得包含可 blittable 的引用。

【讨论】:

  • 这可能意味着如果我使我的结构记录结构,则收益为零。
  • @cmadh 有一些优点:您可以免费获得 ToString 实现和运算符 != 和 ==,并且可以使用 with 关键字复制它们。
猜你喜欢
  • 2016-11-28
  • 2017-11-14
相关资源
最近更新 更多