#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, вероятно, просто прекрасно.