【问题标题】:Weird span behaviour奇怪的跨度行为
【发布时间】:2022-11-30 19:03:33
【问题描述】:

在 C# 中使用 Spans 时,我得到了一些奇怪的结果,我不确定我做错了什么。为了解决问题,我做了一个简单的测试用例:

        public static void DecSpans(Span<byte> b1, Span<byte> b2)
        {
            for (int i = 0; i < b1.Length; ++i)
            {
                b1[i] = (byte)(b1[i] - b2[i]);
            }

        }

        [DataTestMethod]
        public void TestSpan()
        {
            byte[] buf1 = new byte[4] { 1, 2, 3, 4 };
            DecSpans(buf1[..], buf1);
            Assert.IsTrue(buf1.All(b => b == 0));
        }

buf1 当我把它做成切片时,由于某种原因没有被修改。如果我删除 [..],则修改 buf1。我在这里做违法的事吗?

【问题讨论】:

    标签: c#


    【解决方案1】:

    与跨度无关。

    当你对一个类型使用切片运算符时,你会得到一个相同类型的实例。所以当你在数组上使用切片时,你会得到一个新数组。

    因此buf1[..]buf1.ToArray() 相同:它分配一个新数组并将buf1 复制到其中。然后重新分配这个临时数组中的元素,并丢弃它。

    要创建指向数组的跨度,请使用buf1.AsSpan()


    我想你已经习惯了 Rust,其中一个切片产生它自己的专用类型。这不是 C# 的工作方式。例如,创建指向 List&lt;T&gt; 的底层存储的 Span&lt;T&gt; 是不安全的(因为该存储可以随着列表的增长而重新分配)。如果一个切片总是产生一个Span&lt;T&gt;,那么对列表进行切片要么被禁止,要么不安全,这两者都是不可取的(并且 C# 没有借用检查器来保证安全)。遵循切片返回相同类型的实例的规则可以缓解这种情况。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-11-14
      • 1970-01-01
      • 2011-03-19
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多