내용 보기
작성자
관리자 (IP : 172.17.0.1)
날짜
2021-01-11 10:35
제목
[C#] ReadOnlySequence<T> 소개
|
이번엔 다음의 글을 정리한 것에 불과합니다. CREATING A READONLYSEQUENCE FROM ARRAY DATA ; https://www.stevejgordon.co.uk/creating-a-readonlysequence-from-array-data-in-dotnet
ReadOnlySequence<T> Struct ; https://docs.microsoft.com/en-us/dotnet/api/system.buffers.readonlysequence-1
public ReadOnlySequence(ReadOnlyMemory<T> memory) public ReadOnlySequence(T[] array) public ReadOnlySequence(T[] array, int start, int length)
public ReadOnlySequence(ReadOnlySequenceSegment<T> startSegment, int startIndex, ReadOnlySequenceSegment<T> endSegment, int endIndex)
ReadOnlySequenceSegment<T> Class ; https://docs.microsoft.com/en-us/dotnet/api/system.buffers.readonlysequencesegment-1
namespace System.Buffers
{
public abstract class ReadOnlySequenceSegment<T>
{
public ReadOnlyMemory<T> Memory { get; protected set; }
public ReadOnlySequenceSegment<T>? Next { get; protected set; }
public long RunningIndex { get; protected set; }
}
}
class ArraySegment<T> : ReadOnlySequenceSegment<T>
{
public ArraySegment(T [] array)
{
this.Memory = array;
}
public ArraySegment<T> Add(T [] array)
{
var segment = new ArraySegment<T>(array);
segment.RunningIndex = RunningIndex + Memory.Length;
Next = segment;
return segment;
}
}
class Program
{
static void Main(string[] args)
{
int[] array1 = { 1, 2, 3 };
int[] array2 = { 6, 7, 8, 9, 10 };
ArraySegment<int> segment1 = new ArraySegment<int>(array1);
ArraySegment<int> segment2 = segment1.Add(array2);
ReadOnlySequence<int> seq = new ReadOnlySequence<int>(segment1, 0, segment2, segment2.Memory.Length);
foreach (var segment in seq)
{
foreach (int item in segment.Span)
{
Console.Write(item + ", ");
}
}
Console.WriteLine();
}
}
/* 출력 결과
1, 2, 3, 6, 7, 8, 9, 10
*/
{
int[] array1 = { 1, 2, 3 };
int[] array2 = { 4, 5, };
int[] array3 = { 6, 7, 8, 9, 10 };
ArraySegment<int> segment1 = new ArraySegment<int>(array1);
ArraySegment<int> segment3 = segment1.Add(array2).Add(array3);
ReadOnlySequence<int> seq = new ReadOnlySequence<int>(segment1, 0, segment3, segment3.Memory.Length);
foreach (var segment in seq)
{
foreach (int item in segment.Span)
{
Console.Write(item + ", ");
}
}
Console.WriteLine();
}
/* 출력 결과
1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
*/
그런데, 사실 여러 개의 분리된 버퍼를 연결해 주는 것에 그치지 않고 열거 자체를 자연스럽게 해주면 더 좋았을 것입니다. 이런 용도의 확장 메서드를 만들어 구현할 수도 있지만, public static class Extension
{
public static IEnumerable<T> AsEnumerable<T>(this ReadOnlySequence<T> seq)
{
foreach (var segment in seq)
{
int len = GetLength(segment); // https://www.sysnet.pe.kr/2/0/12481
for (int i = 0;i < len; i ++)
{
yield return GetItem(segment, i);
}
}
}
private static T GetItem
SequenceReader<T> Struct ; https://docs.microsoft.com/en-us/dotnet/api/system.buffers.sequencereader-1 AN INTRODUCTION TO SEQUENCEREADER ; https://www.stevejgordon.co.uk/an-introduction-to-sequencereader
SequenceReader<int> reader = new SequenceReader<int>(seq);
while (reader.End is false)
{
if (reader.TryRead(out int item) == true)
{
Console.Write($"{item}, ");
}
}
public static IEnumerable<T> AsEnumerable<T>(this ReadOnlySequence<T> seq) where T : unmanaged, IEquatable<T>
{
SequenceReader<T> reader = new SequenceReader<T>(seq);
// Error CS4013 Instance of type 'SequenceReader<T>' cannot be used inside a nested function, query expression, iterator block or async method
while (reader.End is false)
{
if (reader.TryRead(out T item) == true)
{
yield return item;
}
}
}
|
출처1
https://www.sysnet.pe.kr/Default.aspx?mode=2&sub=0&pageno=0&detail=1&wid=12484
출처2
