Определение пользовательского класса коллекции на основе списка. Как получить доступ к элементам, которые хранятся в экземпляре? - PullRequest
0 голосов
/ 01 мая 2019

Создание собственного класса сбора данных, который наследует методы из List.Этот новый тип хранит элементы в очереди, имеет частный словарь, в котором хранятся все элементы и соответствующие идентификаторы, который при добавлении нового элемента проверяет, есть ли уже элемент с таким же идентификатором в очереди, и заменяет его.Интересно, есть ли способ получить доступ к этому элементу (который имеет тот же идентификатор) и перезаписать его.

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

public void Enqueue(T item, string uniqueID)
    {
        if (entries.ContainsKey(uniqueID))
        {
            int index = base.IndexOf(entries[uniqueID]);
            base.Remove(entries[uniqueID]);
            base.Insert(index, item);
            entries[uniqueID] = item;
        }
        else
        {
            base.Add(item);
            entries.Add(uniqueID, item);
        }
    }

entries - это словарь, содержащий строку и T

Это определение всего класса

using System.Collections;
using System.Collections.Generic;
using System;
using System.Linq;
/// <summary>
/// Queue based on class that has only one entry with unique ID
/// </summary>
/// /// /// <remarks>
/// When adding value with same ID old value is overwriten but place in the queue is maintained
/// </remarks>
/// <typeparam name="T"></typeparam>

public class ListQueueSet<T>:List<T>
{
    new public void Add(T item) { throw new NotSupportedException(); }
    new public void AddRange(IEnumerable<T> collection) { throw new NotSupportedException(); }
    new public void Insert(int index, T item) { throw new NotSupportedException(); }
    new public void InsertRange(int index, IEnumerable<T> collection) { throw new NotSupportedException(); }
    new public void Reverse() { throw new NotSupportedException(); }
    new public void Reverse(int index, int count) { throw new NotSupportedException(); }
    new public void Sort() { throw new NotSupportedException(); }
    new public void Sort(Comparison<T> comparison) { throw new NotSupportedException(); }
    new public void Sort(IComparer<T> comparer) { throw new NotSupportedException(); }
    new public void Sort(int index, int count, IComparer<T> comparer) { throw new NotSupportedException(); }
    new public void Remove(T item) { throw new NotSupportedException(); }

    private Dictionary<string, T> entries;

    public ListQueueSet()
    {
        entries = new Dictionary<string, T>();
    }

    public void Enqueue(T item, string uniqueID)
    {
        if (entries.ContainsKey(uniqueID))
        {
            int index = base.IndexOf(entries[uniqueID]);
            base.Remove(entries[uniqueID]);
            base.Insert(index, item);
            entries[uniqueID] = item;
        }
        else
        {
            base.Add(item);
            entries.Add(uniqueID, item);
        }
    }

    public T Dequeue()
    {
        var t = base[0];
        base.RemoveAt(0);

        entries.Remove(entries.FirstOrDefault(x => x.Value.Equals(t)).Key);
        return t;
    }

    public T Peek()
    {
        return base[0];
    }
}

Ответы [ 2 ]

0 голосов
/ 02 мая 2019

Как уже упоминалось в комментариях, вы не должны наследовать от List и выставлять все те функции, которые вам не нужны.Для тех, кто использует вашу структуру данных, это будет просто запутанно.Кроме того, использование OrderedDictionary сделает ваш код более простым, так как к нему можно получить доступ как по ключу, так и по индексу.

public class MyQueue<T>
{ 
    private OrderedDictionary items = new OrderedDictionary();

    public void Enqueue(T item, string uniqueID)
    {
        if(items.Contains(uniqueID))
            items[uniqueID] = item;
        else
            items.Add(uniqueID, item);
    }

    public T Dequeue()
    {
        var item = items[0];
        items.RemoveAt(0);
        return (T)item;
    }

    public T Peek()
    {
        return (T)items[0];
    }
}

Кроме того, ваши усилия по предотвращению использования функций List можно легко обойти, приведя кбазовый тип.

var queue = new ListQueueSet<int>();
((List<int>)queue).Add(1); //This will add 1 to the collection
0 голосов
/ 02 мая 2019
int index = base.IndexOf(entries[uniqueID]);
this[index] = item;
entries[uniqueID] = item;

очевидно, this[index] позволяет вам получить доступ к списку, который вы объявляете

...