Существует ли разреженный промежуток для нескольких разделов памяти?

#c# #.net #system.memory

Вопрос:

Считать:

         public struct Foo
        {
            public float value;
        }

        static void Main(string[] args)
        {
            var array = new Foo[10];

            var block1 = new Memory<Foo>(array, 0, 3);
            var block2 = new Memory<Foo>(array, 4, 6);

            var span1 = block1.Span;
            var span2 = block2.Span;

            foreach (ref var  f in span1) { /* do work */ }
            foreach (ref var  f in span2) { /* do work */ }

            var blocks = new[] { block1, block2 };

            foreach (var block in blocks)
            {
                foreach (ref var f in block.Span)
                {
                    /* do work */
                }
            }

            // preferred would be:
            foreach (ref var f in new Span<Foo>(blocks))
            {
                /* do work */
            }
        }
 

Существует ли пространственная структура, которая позволяет охватывать несколько блоков памяти? Я мог бы написать пользовательский перечислитель, но вызывающий память.Интервал для каждого элемента медленный.

Комментарии:

1. Это звучит так, как будто вы пытаетесь решить проблему на неправильном уровне абстракции. Если у вас несколько Memory s и вы не можете сделать никаких предположений о них, вы мало что можете сделать, кроме как получить доступ к ним в виде промежутков по порядку. С другой стороны, если вы работаете с непрерывной памятью, вам не нужно будет передавать несколько Memory s-просто передайте один с соответствующим диапазоном или превратите его в один диапазон при доступе и срежьте его по мере необходимости.

2. @JeroenMostert да, ты совершенно прав. На самом деле это просто полезность/сахар. Я могу сделать это так, как я написал, просматривая их, но я не был уверен, существует ли более чистый механизм для выражения этого шаблона или нет.

3. Вложенные циклы foreach, вероятно, являются лучшим способом для этого. Вы могли бы использовать foreach (var f in blocks.SelectMany(b => b.Span.ToArray())) , но это будет медленнее

4. Самое простое решение иногда бывает лучшим решением. То, как вы это написали, на самом деле не страшно и вполне понятно. Если вы ищете однострочное решение, другим вариантом может быть приведение к списку и использование List<T>.ForEach( )<T> как blocks.ToList().ForEach(block => block.Span.ToList().ForEach(f => /* Action */)); . Но это, вероятно, медленнее и намного менее читабельно для следующего разработчика. То, как вы это делаете с вложенными циклами foreach, вероятно, просто прекрасно.