Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/arrays/14.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# ArraySegment有什么用<;T>;上课?_C#_Arrays_.net - Fatal编程技术网

C# ArraySegment有什么用<;T>;上课?

C# ArraySegment有什么用<;T>;上课?,c#,arrays,.net,C#,Arrays,.net,在对MessageEncoder类进行子类化时,我遇到了ArraySegment类型 我现在了解到它是给定数组的一段,具有偏移量,不可枚举,并且没有索引器,但我仍然无法理解它的用法。有人能举例说明吗 IO类的缓冲区分区-同时使用相同的缓冲区 读写操作,并具有 单一结构,你可以通过 描述了您的整个操作 集合函数-从数学上讲,你可以表示任何 使用此新函数的连续子集 结构。这基本上意味着你 可以创建阵列的分区, 但你不能代表所有的可能性 晚上好。注意电话 1提出的挑逗者可能会 使用 ArraySegm

在对
MessageEncoder
类进行子类化时,我遇到了
ArraySegment
类型

我现在了解到它是给定数组的一段,具有偏移量,不可枚举,并且没有索引器,但我仍然无法理解它的用法。有人能举例说明吗

  • IO类的缓冲区分区-同时使用相同的缓冲区 读写操作,并具有 单一结构,你可以通过 描述了您的整个操作
  • 集合函数-从数学上讲,你可以表示任何 使用此新函数的连续子集 结构。这基本上意味着你 可以创建阵列的分区, 但你不能代表所有的可能性 晚上好。注意电话 1提出的挑逗者可能会 使用 ArraySegment分区和树 结构。最后的数字可能是 已通过遍历写出 树的深度优先。这本应该 在以下方面,这是一个理想的场景: 记忆和速度我相信
  • 多线程-您现在可以生成多个线程在 使用分段时使用相同的数据源 阵列作为控制门。循环 现在可以使用离散计算 很容易被外派出去,什么的 最新的C++编译器是 开始做代码优化 步骤
  • UI分段-使用分段约束UI显示 结构。你现在可以去商店了 表示数据页的结构 这可以很快应用于 显示功能。单一连续 可以使用数组来显示 离散视图,甚至分层视图 结构,例如 通过分割线性数据进行TreeView 存储到节点集合段中
  • 在本例中,我们将介绍如何使用原始数组、偏移量和计数属性,以及如何循环ArraySegment中指定的元素

    using System;
    
    class Program
    {
        static void Main()
        {
            // Create an ArraySegment from this array.
            int[] array = { 10, 20, 30 };
            ArraySegment<int> segment = new ArraySegment<int>(array, 1, 2);
    
            // Write the array.
            Console.WriteLine("-- Array --");
            int[] original = segment.Array;
            foreach (int value in original)
            {
                Console.WriteLine(value);
            }
    
            // Write the offset.
            Console.WriteLine("-- Offset --");
            Console.WriteLine(segment.Offset);
    
            // Write the count.
            Console.WriteLine("-- Count --");
            Console.WriteLine(segment.Count);
    
            // Write the elements in the range specified in the ArraySegment.
            Console.WriteLine("-- Range --");
            for (int i = segment.Offset; i < segment.Count+segment.Offset; i++)
            {
                Console.WriteLine(segment.Array[i]);
            }
        }
    }
    
    使用系统;
    班级计划
    {
    静态void Main()
    {
    //从此数组创建ArraySegment。
    int[]数组={10,20,30};
    ArraySegment段=新的ArraySegment(数组,1,2);
    //写入数组。
    Console.WriteLine(“--Array-->”);
    int[]original=segment.Array;
    foreach(原始的int值)
    {
    控制台写入线(值);
    }
    //写偏移量。
    Console.WriteLine(“--Offset--”);
    控制台写入线(段偏移);
    //记下计数。
    Console.WriteLine(“--Count--”);
    控制台写入线(段数);
    //在ArraySegment中指定的范围内写入元素。
    Console.WriteLine(“--Range--”);
    对于(int i=段.Offset;i<段.Count+段.Offset;i++)
    {
    Console.WriteLine(段.Array[i]);
    }
    }
    }
    

    它是一个小小的士兵结构,除了保留对数组的引用和存储索引范围外,什么也不做。有点危险,注意它不会复制数组数据,也不会以任何方式使数组不可变或表示需要不可变。更典型的编程模式是只保留或传递数组和长度变量或参数,就像在.NET beginhead()方法、String.SubString()、Encoding.GetString()等中所做的那样

    它在.NET框架内没有太多的用途,除了一位从事web套接字和WCF工作的特定Microsoft程序员喜欢它之外。这可能是正确的指导,如果你喜欢,那么就使用它。它确实在.NET4.6中做了一个peek-a-boo,添加的MemoryStream.TryGetBuffer()方法使用了它。与我假设的两个
    out
    参数相比,我更喜欢

    总的来说,更普遍的切片概念在主要的.NET工程师(如Mads Torgersen和Stephen Toub)的愿望清单上很高。后者在不久前启动了
    array[:]
    语法提案,您可以看到他们在中的想法。我认为获得CLR支持是最终的关键。对于C#version 7,我们正在积极考虑这一点。afaik,请密切关注

    更新:死链接,这是在7.2版中发布的


    更新2:C#version 8.0中对范围和索引类型以及Slice()方法的更多支持。

    ArraySegment
    在+中变得更加有用,现在它实现了:

    • IList
    • i收集
    • IEnumerable
    • IEnumerable
    • IReadOnlyList
    • IReadOnlyCollection
    与之相反,它没有实现任何接口

    该类现在能够参与到LINQ的奇妙世界中,因此我们可以执行LINQ的常规操作,如查询内容、在不影响原始数组的情况下反转内容、获取第一项,等等:

    var array = new byte[] { 5, 8, 9, 20, 70, 44, 2, 4 };
    array.Dump();
    var segment = new ArraySegment<byte>(array, 2, 3);
    segment.Dump(); // output: 9, 20, 70
    segment.Reverse().Dump(); // output 70, 20, 9
    segment.Any(s => s == 99).Dump(); // output false
    segment.First().Dump(); // output 9
    array.Dump(); // no change
    
    var数组=新字节[]{5,8,9,20,70,44,2,4};
    array.Dump();
    var段=新数组段(数组,2,3);
    段.转储();//产出:9、20、70
    段.Reverse().Dump();//产出70、20、9
    segment.Any(s=>s==99).Dump();//输出错误
    段.First().Dump();//产出9
    array.Dump();//无变化
    
    包装器类是什么?只是为了避免将数据复制到临时缓冲区

    public class SubArray<T> {
            private ArraySegment<T> segment;
    
            public SubArray(T[] array, int offset, int count) {
                segment = new ArraySegment<T>(array, offset, count);
            }
            public int Count {
                get { return segment.Count; }
            }
    
            public T this[int index] {
                get {
                   return segment.Array[segment.Offset + index];
                }
            }
    
            public T[] ToArray() {
                T[] temp = new T[segment.Count];
                Array.Copy(segment.Array, segment.Offset, temp, 0, segment.Count);
                return temp;
            }
    
            public IEnumerator<T> GetEnumerator() {
                for (int i = segment.Offset; i < segment.Offset + segment.Count; i++) {
                    yield return segment.Array[i];
                }
            }
        } //end of the class
    

    ArraySegment比您想象的有用得多。试着运行下面的单元测试,准备好惊讶吧

        [TestMethod]
        public void ArraySegmentMagic()
        {
            var arr = new[] {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
    
            var arrSegs = new ArraySegment<int>[3];
            arrSegs[0] = new ArraySegment<int>(arr, 0, 3);
            arrSegs[1] = new ArraySegment<int>(arr, 3, 3);
            arrSegs[2] = new ArraySegment<int>(arr, 6, 3);
            for (var i = 0; i < 3; i++)
            {
                var seg = arrSegs[i] as IList<int>;
                Console.Write(seg.GetType().Name.Substring(0, 12) + i);
                Console.Write(" {");
                for (var j = 0; j < seg.Count; j++)
                {
                    Console.Write("{0},", seg[j]);
                }
                Console.WriteLine("}");
            }
        }
    

    简单地说:它保留对数组的引用,允许您对单个数组变量进行多个引用,每个引用的范围不同

    事实上,它可以帮助您以更结构化的方式使用和传递数组的部分,而不是使用多个变量来保存起始索引和长度。此外,它还提供了收集接口,以便更轻松地使用阵列
    3
    4
    
    3
    4
    
        [TestMethod]
        public void ArraySegmentMagic()
        {
            var arr = new[] {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
    
            var arrSegs = new ArraySegment<int>[3];
            arrSegs[0] = new ArraySegment<int>(arr, 0, 3);
            arrSegs[1] = new ArraySegment<int>(arr, 3, 3);
            arrSegs[2] = new ArraySegment<int>(arr, 6, 3);
            for (var i = 0; i < 3; i++)
            {
                var seg = arrSegs[i] as IList<int>;
                Console.Write(seg.GetType().Name.Substring(0, 12) + i);
                Console.Write(" {");
                for (var j = 0; j < seg.Count; j++)
                {
                    Console.Write("{0},", seg[j]);
                }
                Console.WriteLine("}");
            }
        }
    
    ArraySegment0 {0,1,2,}
    ArraySegment1 {3,4,5,}
    ArraySegment2 {6,7,8,}
    
            byte[] arr1 = new byte[] { 1, 2, 3, 4, 5, 6 };
            ArraySegment<byte> seg1 = new ArraySegment<byte>(arr1, 2, 2);
            MessageBox.Show((seg1 as IList<byte>)[0].ToString());
    
            byte[] arr1 = new byte[] { 1, 2, 3, 4, 5, 6 };
            int offset = 2;
            int length = 2;
            byte[] arr2 = arr1;
            MessageBox.Show(arr2[offset + 0].ToString());