Как переопределить List <T> Добавить метод в С#?
В настоящее время я ищу свою собственную коллекцию, которая будет похожа на обычный список, за исключением того, что она будет содержать только 10 элементов. Если элемент был добавлен, когда в списке было уже 10 элементов, первый элемент будет удален до добавления нового элемента.
Я хочу создать класс, который расширяет System.Collections.Generic.List<T>
, а затем изменяет метод Add(T item)
, чтобы включить функциональность, которая удаляет первый элемент, если это необходимо.
Ответы
Ответ 1
Во-первых, вы не можете переопределить Add и по-прежнему иметь полиморфизм против List, что означает, что если вы используете новое ключевое слово и ваш класс как List, ваш новый метод Add не будет вызываться.
Во-вторых, я предлагаю вам изучить класс Queue, поскольку то, что вы пытаетесь сделать, это скорее очередь, чем список, Класс оптимизирован именно для того, что вы хотите сделать, но не имеет какого-либо ограничителя размера.
Если вы действительно хотите, чтобы что-то действовало как List, но работало как очередь с максимальным размером, я предлагаю вам реализовать IList и сохранить экземпляр очереди для хранения ваших элементов.
Например:
public class LimitedQueue<T> : IList<T>
{
public int MaxSize {get; set;}
private Queue<T> Items = new Queue<T>();
public void Add(T item)
{
Items.Enqueue(item);
if(Items.Count == MaxSize)
{
Items.Dequeue();
}
}
// I'll let you do the rest
}
Ответ 2
Вы также можете реализовать метод добавления с помощью
public new void Add(...)
в производном классе, чтобы скрыть существующее добавление и ввести ваши функции.
Изменить: грубая схема...
class MyHappyList<T> : List<T>
{
public new void Add(T item)
{
if (Count > 9)
{
Remove(this[0]);
}
base.Add(item);
}
}
Просто заметите, что это подразумевалось, но вы всегда должны ссылаться на свой собственный список по фактическому типу, а не по базовому типу/интерфейсу, поскольку метод скрытия доступен только для вашего типа и других производных типов.
Ответ 3
Вы не можете переопределить Add(), это не виртуальный метод. Выведите из IList вместо этого и используйте частный член очереди для реализации.
Ответ 4
Вы можете расширить System.Collections.ObjectModel.Collection и переопределить метод InsertItem, чтобы получить нужное поведение, а также реализует IList
Ответ 5
Вы можете просто написать класс, который реализует IList<T>
, который содержит внутренний List<T>
и записывает ваши собственные методы.
Ответ 6
Похоже, что я могу это сделать:
class MostRecentList<T> : System.Collections.Generic.List<T> {
private int capacity;
public MostRecentList(int capacity) : base() {
this.capacity = capacity;
}
public new void Add(T item) {
if (base.Count == capacity) {
base.RemoveAt(0);
}
base.Add(item);
}
}
Так как метод add()
не помечен как виртуальный.
Ответ 7
Ваше описание вашего требования звучит как Круговой буфер.
Я реализовал свою собственную - аналогичную эту реализацию в CodePlex, за исключением того, что моя реализует IList<T>
.
Некоторые другие ответы предполагают использование Queue<T>
- но это не совсем то же самое, поскольку он позволяет только доступ к FIFO.
Как правило, не рекомендуется выводить из List<T>
- вместо этого выводить из Collection<T>
и внедрять любые дополнительные вещи, которые вам нужны. Но для кругового буфера, вероятно, более целесообразно использовать частный массив, а не получать из Collection<T>
, как реализация CodePlex.
Ответ 8
Вы можете посмотреть библиотеку коллекции C5. Они имеют ArrayList <T> который реализует IList <T> и иметь виртуальный метод Add. Библиотека коллекции C5 представляет собой удивительную коллекцию списков, очередей, стеков и т.д. Здесь вы можете найти библиотеку C5:
http://www.itu.dk/research/c5/
Ответ 9
Прочитайте Принцип замены Лискова, ваша коллекция - очень плохой кандидат на расширение List <T>
, это даже не отличный кандидат на реализацию IList <T>
.
Какие шаблоны считывания необходимы для этих данных? Если вам нужно всего лишь просмотреть все текущие записи, то для начала использования IEnumerable <T>
и метода Add (T) должно быть достаточно.
Затем это может быть реализовано частной Queue (или Deque будет лучше, но для такой коллекции потребуется некоторый другой API коллекций, и я не предлагаю вам попробовать его реализовать самостоятельно), к которому вы добавили Enqueue() во время добавления ( с Dequeue, если необходимо для поддержания размера).
Обратите внимание: реализация IEnumerable и предоставление метода Add означает, что при необходимости вы можете использовать синтаксис инициализатора коллекции.
Если вам нужен произвольный доступ к значениям, тогда внедрение индексатора может быть хорошей идеей, но я не вижу, какую выгоду это даст вам без лишнего контекста по этому вопросу.
Ответ 10
Вы можете попробовать расширить System.Collections.ObjectModel.Collection<T>
, что намного более гибко. Затем вы можете переопределить защищенные члены InsertItem
и SetItem
, чтобы настроить поведение вашей коллекции.