2013-12-03 2 views
0

мне интересно, о какой-то функциональности в C# ...C# - конечный список или ограниченный список?

Я хотел бы иметь List<Object> MyList();, которую я мог .Add(new Object()) конечное количество раз. Скажем, я добавил 5 пунктов, и если бы я добавил шестой, то последний элемент будет уничтожен, и этот шестой элемент будет помещен поверх списка.

Есть ли встроенный механизм в C#, который делает это?

+1

«Последний элемент» довольно неоднозначный. Вы имеете в виду последнее или старшее? –

+1

Ты имеешь в виду, как круговой буффер? –

+0

, которого нет, но есть тонна реализаций. –

ответ

1

Там нет сборки в коллекции в Основе, как сказал Servy. Тем не менее, вы можете сделать это как кольцевой буфер -

enter image description here

namespace DataStructures 
{ 
    class Program 
    { 
     static void Main(string[] args) 
     { 
      var buffer = new CircularBuffer<int>(capacity: 3); 

      while (true) 
      { 
       int value; 
       var input = Console.ReadLine(); 

       if (int.TryParse(input, out value)) 
       { 
        buffer.Write(value); 
        continue; 
       } 
       break; 
      } 

      Console.WriteLine("Buffer: "); 
      while (!buffer.IsEmpty) 
      { 
       Console.WriteLine(buffer.Read()); 
      } 
      Console.ReadLine(); 
     } 
    } 
} 

namespace DataStructures 
{ 
    public class CircularBuffer<T> 
    { 
     private T[] _buffer; 
     private int _start; 
     private int _end; 

     public CircularBuffer() 
      : this(capacity: 3) 
     { 
     } 

     public CircularBuffer(int capacity) 
     { 
      _buffer = new T[capacity + 1]; 
      _start = 0; 
      _end = 0; 
     } 

     public void Write(T value) 
     { 
      _buffer[_end] = value; 
      _end = (_end + 1) % _buffer.Length; 
      if (_end == _start) 
      { 
       _start = (_start + 1) % _buffer.Length; 
      } 
     } 

     public T Read() 
     { 
      T result = _buffer[_start]; 
      _start = (_start + 1) % _buffer.Length; 
      return result; 
     } 

     public int Capacity 
     { 
      get { return _buffer.Length; } 
     } 

     public bool IsEmpty 
     { 
      get { return _end == _start; } 
     } 

     public bool IsFull 
     { 
      get { return (_end + 1) % _buffer.Length == _start; } 
     } 
    } 
} 

Над кодом от PluralSight - Scott Allen's C# Generics.

+0

Простой, но эффективный. Мне это нравится, спасибо! – ojek

1

В моей основной библиотеке у меня есть что-то, называемое LimitedQueue<T>. Вероятно, это похоже на то, что вам нужно (вы можете легко изменить его, чтобы вместо этого было List<T>). (Source on GitHub)

using System.Collections.Generic; 

namespace Molten.Core 
{ 
    /// <summary> 
    /// Represents a limited set of first-in, first-out objects. 
    /// </summary> 
    /// <typeparam name="T">The type of each object to store.</typeparam> 
    public class LimitedQueue<T> : Queue<T> 
    { 
     /// <summary> 
     /// Stores the local limit instance. 
     /// </summary> 
     private int limit = -1; 

     /// <summary> 
     /// Sets the limit of this LimitedQueue. If the new limit is greater than the count of items in the queue, the queue will be trimmed. 
     /// </summary> 
     public int Limit 
     { 
      get 
      { 
       return limit; 
      } 
      set 
      { 
       limit = value; 
       while (Count > limit) 
       { 
        Dequeue(); 
       } 
      } 
     } 

     /// <summary> 
     /// Initializes a new instance of the LimitedQueue class. 
     /// </summary> 
     /// <param name="limit">The maximum number of items to store.</param> 
     public LimitedQueue(int limit) 
      : base(limit) 
     { 
      this.Limit = limit; 
     } 

     /// <summary> 
     /// Adds a new item to the queue. After adding the item, if the count of items is greater than the limit, the first item in the queue is removed. 
     /// </summary> 
     /// <param name="item">The item to add.</param> 
     public new void Enqueue(T item) 
     { 
      while (Count >= limit) 
      { 
       Dequeue(); 
      } 
      base.Enqueue(item); 
     } 
    } 
} 

Вы бы использовать его как это: не

LimitedQueue<int> numbers = new LimitedQueue<int>(5); 
numbers.Enqueue(1); 
numbers.Enqueue(2); 
numbers.Enqueue(3); 
numbers.Enqueue(4); 
numbers.Enqueue(5); 
numbers.Enqueue(6); // This will remove "1" from the list 
// Here, "numbers" contains 2, 3, 4, 5, 6 (but not 1). 
+1

Вы действительно не должны расширять «Queue» или другие коллекции, чтобы изменять такие функции, как это, учитывая, что методы, которые вам нужно влиять, не являются «виртуальными». Возможность иметь объект, набранный как супер-тип, позволяет вам нарушать инварианты, которые этот тип намерен удерживать, что обычно является довольно большой проблемой. – Servy

+0

И, как я прокомментировал другое сообщение: это не позволит случайного удаления. Было четко указано, что это «Список». –

+0

@Servy Да, но, вообще говоря, если вы поддерживаете кодовую базу (в отличие от плагинов от третьих лиц или что-то в этом роде), вы бы знали, как правильно использовать этот класс, и все будет хорошо. Кроме того, если Microsoft действительно хотела, чтобы люди не распространялись на базовые типы коллекций, они бы «запечатали» их.;) – qJake

2

Ни один из встроенных в коллекции будут делать это, но вы можете легко сделать свой собственный класс, который имеет внутренний список который имеет такое поведение при добавлении элемента. Это не особенно сложно, но выписать все методы, которые стандартный список будет использовать и реализовать все интерфейсы List, может быть немного утомительным.

+0

Простейшим было бы просто обернуть добавление в список в методе и направить его оттуда. –

+0

@JeroenVannevel Если это используется только в довольно малой области видимости и все внутреннее для приложения, то, возможно, да. Это становится проблемой, если вы хотите выставить коллекцию на более широкую базу кода или даже в качестве части открытого API. – Servy

-1

Вы можете использовать Очередь с фиксированным размером. Просто позвоните .ToList().

Fixed size queue which automatically dequeues old values upon new enques

+0

Код в этом сообщении является суб-par, на мой взгляд, он даже не расширяет базовый класс .NET collection. (Я не был тем, кто вас ниспровергал.) – qJake

+1

@SpikeX [Это хорошая * вещь, которая не расширяет базовую сборку .NET.] (Http://stackoverflow.com/questions/20361269/c -sharp-final-list-or-limit-list # comment30397119_20361327) Конечно, некоторые из ответов имеют другие проблемы, такие как блокировка на неявной ссылке на объект. – Servy

+0

@Servy Правильно, как я с тех пор узнал. ;) (К сожалению, я больше не могу редактировать свой комментарий.) – qJake

Смежные вопросы