首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >创建不复制的ImmutableArray

创建不复制的ImmutableArray
EN

Stack Overflow用户
提问于 2018-07-12 07:49:05
回答 6查看 2.2K关注 0票数 5

有没有任何方法(可能是肮脏的黑客)来创建一个ImmutableArray,它只使用指定的数组,而不是复制它?

我有一个我知道不会改变的数组,我想创建一个ImmutableArray来允许客户端安全地访问我的数组。

查看ImmutableArray的源代码,我看到Create方法没有帮助:

代码语言:javascript
复制
public static ImmutableArray<T> Create<T>(params T[] items)
{
    if (items == null)
    {
        return Create<T>();
    }

    // We can't trust that the array passed in will never be mutated by the caller.
    // The caller may have passed in an array explicitly (not relying on compiler params keyword)
    // and could then change the array after the call, thereby violating the immutable
    // guarantee provided by this struct. So we always copy the array to ensure it won't ever change.
    return CreateDefensiveCopy(items);
}

编辑:在GitHub上有一个关于这个特性的请求,这也给出了使用最快的黑客:https://github.com/dotnet/corefx/issues/28064

EN

回答 6

Stack Overflow用户

回答已采纳

发布于 2018-07-12 09:15:45

还有另外两种方法,这两种方法都是在这里建议的:https://stackoverflow.com/a/3799030/4418060 (一个在答复中,一个在评论中)。

  1. 从一种结构到另一种结构。
  2. 不安全地把一个扔给另一个。

首先,创建一个新的struct类型,它反映ImmutableArray的布局(这是一个T[]字段),并更改该结构的类型,如CLR (运行时)所见。结构将如下所示:

代码语言:javascript
复制
public struct HackImmutableArray<T>
{
    public T[] Array;
}
  1. 编组: 静态(ImmutableArray)Marshal.PtrToStructure(handle.AddrOfPinnedObject(),ImmutableArray HackyMakeImmutable(T[]数组){ var arrayObject =(Object)新HackImmutableArray { array = Array };var句柄= GCHandle.Alloc(arrayObject,GCHandleType.Pinned);var不变=HackyMakeImmutable类型(T);handle.Free();返回不变};
  2. 不安全铸造(尼斯助手写在这里,在这篇博客文章中找到)。强制转换使用在Unsafe中可用的System.Runtime.CompilerServices.Unsafe NuGet静态类 使用System.Runtime.CompilerServices;静态ImmutableArray HackyMakeImmutable(T[]数组){返回Unsafe.As(ref数组);}

第二个选项是“不安全”,但非常安全,因为我们可以肯定地假定ImmutableArray的结构布局不会改变,这是一个定义特性,而且它可能比任何其他解决方案都快得多。

票数 4
EN

Stack Overflow用户

发布于 2018-07-12 08:01:54

如果您知道数组的确切长度,则可以使用ImmutableArray.CreateBuilder<>加上将从Builder内部创建ImmutableArray<>.MoveToImmutable(),而无需复制它:

代码语言:javascript
复制
var builder = ImmutableArray.CreateBuilder<int>(4);
builder.Add(1);
builder.Add(2);
builder.Add(3);
builder.Add(4);
ImmutableArray<int> array = builder.MoveToImmutable();

方法.MoveToImmutable()将引发异常,如果builder.Capacity != builder.Count

注意,构建器的其他方法(如.ToImmutable())将创建数组的副本。

票数 12
EN

Stack Overflow用户

发布于 2018-07-12 09:14:06

https://github.com/dotnet/corefx/issues/28064,他们推荐最快的方法是使用System.Runtime.CompilerServices.Unsafe:

代码语言:javascript
复制
ImmutableArray<T> im = Unsafe.As<T[], ImmutableArray<T>>(ref array);
票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/51300066

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档