воскресенье, 21 сентября 2025 г.

25.09.22, Alice, CircularBuffer, Collections, Arrays

25.09.22, Alice, CircularBuffer, Collections, Arrays

Alisa, CircualarBuffer, Collections

Для реализации такой функциональности можно создать несколько вариантов методов, которые будут заполнять различные типы коллекций. Вот несколько подходов:

1. Через ICollection<T>

csharp

public void GetAllFromLeft(ICollection<T> collection)

{

    _lock.EnterReadLock();

    try

    {

        int current = start;

        for (int i = 0; i < count; i++)

        {

            collection.Add(buffer[current]);

            current = (current + 1) % capacity;

        }

    }

    finally

    {

        _lock.ExitReadLock();

    }

}

 

public void GetAllFromRight(ICollection<T> collection)

{

    _lock.EnterReadLock();

    try

    {

        int current = (start + count - 1) % capacity;

        for (int i = 0; i < count; i++)

        {

            collection.Add(buffer[current]);

            current = (current - 1 + capacity) % capacity;

        }

    }

    finally

    {

        _lock.ExitReadLock();

    }

}

2. Через массивы

csharp

public void GetAllFromLeft(T[] array)

{

    if (array.Length < count)

        throw new ArgumentException("Массив слишком мал для хранения всех элементов");

 

    _lock.EnterReadLock();

    try

    {

        int current = start;

        for (int i = 0; i < count; i++)

        {

            array[i] = buffer[current];

            current = (current + 1) % capacity;

        }

    }

    finally

    {

        _lock.ExitReadLock();

    }

}

 

public void GetAllFromRight(T[] array)

{

    if (array.Length < count)

        throw new ArgumentException("Массив слишком мал для хранения всех элементов");

 

    _lock.EnterReadLock();

    try

    {

        int current = (start + count - 1) % capacity;

        for (int i = 0; i < count; i++)

        {

            array[i] = buffer[current];

            current = (current - 1 + capacity) % capacity;

        }

    }

    finally

    {

        _lock.ExitReadLock();

    }

}

3. Комбинированный подход с использованием обобщений

Можно создать универсальный метод, который будет работать с любыми коллекциями, реализующими ICollection<T>:

csharp

public void PopulateCollection<TCollection>(TCollection collection)

    where TCollection : ICollection<T>

{

    _lock.EnterReadLock();

    try

    {

        int current = start;

        for (int i = 0; i < count; i++)

        {

            collection.Add(buffer[current]);

            current = (current + 1) % capacity;

        }

    }

    finally

    {

        _lock.ExitReadLock();

    }

}

Важные замечания:

  1. При работе с массивами нужно заранее выделять память нужного размера.
  2. Методы с ICollection<T> будут работать с любыми коллекциями, которые реализуют этот интерфейс (например, List<T>HashSet<T> и т. д.).
  3. Для безопасности потоков используется блокировка _lock.
  4. В случае с массивами добавлена проверка на достаточный размер.
  5. Можно дополнительно добавить обработку исключений и валидацию входных параметров.

Пример использования:

csharp

List<int> list = new List<int>();

buffer.GetAllFromLeft(list);

 

int[] array = new int[buffer.Count];

buffer.GetAllFromRight(array);

Такой подход обеспечивает гибкость и возможность выбора оптимального способа извлечения данных в зависимости от конкретной задачи.

public void PopulateCollection<TCollection>(TCollection collection) where TCollection : ICollection<T> { _lock.EnterReadLock(); try { int current = start; for (int i = 0; i < count; i++) { collection.Add(buffer[current]); current = (current + 1) % capacity; } } finally { _lock.ExitReadLock(); } } Надо две таких функций - PopulateCollectionFromLeft и - PopulateCollectiomFromRight

Вот реализация двух методов:

csharp

// Заполнение коллекции элементами слева направо

public void PopulateCollectionFromLeft<TCollection>(TCollection collection)

    where TCollection : ICollection<T>

{

    _lock.EnterReadLock();

    try

    {

        int current = start; // начинаем с начальной позиции

       

        for (int i = 0; i < count; i++)

        {

            collection.Add(buffer[current]); // добавляем элемент в коллекцию

            current = (current + 1) % capacity; // переходим к следующему элементу с учётом цикличности

        }

    }

    finally

    {

        _lock.ExitReadLock();

    }

}

 

// Заполнение коллекции элементами справа налево

public void PopulateCollectionFromRight<TCollection>(TCollection collection)

    where TCollection : ICollection<T>

{

    _lock.EnterReadLock();

    try

    {

        int current = (start + count - 1) % capacity; // начинаем с последнего элемента

       

        for (int i = 0; i < count; i++)

        {

            collection.Add(buffer[current]); // добавляем элемент в коллекцию

            current = (current - 1 + capacity) % capacity; // переходим к предыдущему элементу с учётом цикличности

        }

    }

    finally

    {

        _lock.ExitReadLock();

    }

}

Объяснение работы методов:

  1. PopulateCollectionFromLeft:
    • начинает обход буфера с позиции start;
    • последовательно добавляет элементы слева направо;
    • использует операцию % capacity для корректной работы с кольцевым буфером;
    • работает с любой коллекцией, реализующей интерфейс ICollection<T>.
  2. PopulateCollectionFromRight:
    • начинает обход с последнего элемента буфера (start + count - 1);
    • добавляет элементы в обратном направлении (справа налево);
    • корректно обрабатывает цикличность буфера через (current - 1 + capacity) % capacity;
    • также работает с любыми коллекциями, реализующими ICollection<T>.

Пример использования:

csharp

var buffer = new ThreadSafeCircularBuffer<int>(5);

buffer.EnqueueRight(1);

buffer.EnqueueRight(2);

buffer.EnqueueRight(3);

buffer.EnqueueRight(4);

buffer.EnqueueRight(5);

 

var listLeft = new List<int>();

buffer.PopulateCollectionFromLeft(listLeft); // [1, 2, 3, 4, 5]

 

var listRight = new List<int>();

buffer.PopulateCollectionFromRight(listRight); // [5, 4, 3, 2, 1]

Дополнительные улучшения:

  • можно добавить проверку на null для параметра collection;
  • добавить обработку исключений при добавлении элементов;
  • добавить проверку на достаточный размер коллекции (если это необходимо);
  • создать перегруженные версии методов с ограничением количества копируемых элементов.

Эти методы обеспечивают гибкую работу с кольцевым буфером и позволяют легко переносить данные в различные типы коллекций.

 

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

Отправить комментарий