Patrick Skelton Ответов: 2

Как выставить частный словарь< K, V> Как коллекцию только для чтения?


Я подозреваю, что быстрого ответа на этот вопрос нет, но все равно спрошу.

У меня есть класс, который имеет:

private Dictionary<string,string> _records = new Dictionary<string,string>();

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

Количество записей в словаре невелико-никогда не превышает низких десятков, - поэтому производительность не является проблемой.

Я не знаю, как получить версию компилятора, но я ориентируюсь на .NET 4.5.2. кажется, у меня есть весь современный синтаксис, о котором я читал, за некоторыми исключениями, такими как именованные поля кортежа, так что я думаю, что это ставит меня на C# 5 (или я могу говорить ерунду)?

Как лучше всего это сделать?

Кстати, в данном конкретном случае я обладаю достаточной гибкостью в отношении того, как взаимодействуют эти два класса. В частности, было бы прекрасно, если бы я мог просто вернуть неизменяемый List<string> о ключах в словаре. Тогда я мог бы просто добавить еще одну функцию, чтобы вернуть значение для указанного ключа.

Я также мог бы бросить Dictionary<string,string> в целом.

Что я уже пробовал:

Я довольно много гуглил на эту тему, но, похоже, там просто тонна противоречивой информации.

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

Richard MacCutchan

Вы можете либо добавить некоторые методы в свой класс, чтобы разрешить другому классу доступ к содержимому. Или создайте метод get, который возвращает временную копию словаря.

CHill60

Опереди меня! Виртуальная 5*

Richard MacCutchan

Ха, мои догадки быстрее твоих. :)

2 Ответов

Рейтинг:
8

Richard Deeming

Цитата:
В частности, было бы прекрасно, если бы я мог просто вернуть неизменяемый список "строка" ключей в словаре. Тогда я мог бы просто добавить еще одну функцию, чтобы вернуть значение для указанного ключа.

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

Я был бы склонен иметь реализацию контейнерного класса IReadOnlyDictionary(TKey, TValue)[^]:
public class Foo : IReadOnlyDictionary<string, string>
{
    private readonly Dictionary<string,string> _records = new Dictionary<string,string>();
    
    public int Count => _records.Count;
    
    // The Dictionary.Keys and Dictionary.Values collections are read-only, so this is OK:
    
    public IEnumerable<string> Keys => _records.Keys;
    
    public IEnumerable<string> Values => _records.Values;
    
    public string this[string key] => _records[key];
    
    public bool ContainsKey(string key) => _records.ContainsKey(key);
    
    public bool TryGetValue(string key, out string value) => _records.TryGetValue(key, out value);
    
    public IEnumerator<KeyValuePair<string, string>> GetEnumerator() => _records.GetEnumerator();
    
    IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
}

NB: У вас может возникнуть искушение просто бросить _records поле к Ан IReadOnlyDictionary<string, string> и верни это. Но это не помешало бы вызывающему коду вернуть его обратно в a Dictionary<string, string> и модифицирует его.

В зависимости от ваших требований, вы также можете взглянуть на неизменяемые коллекции[^] пакет.


Patrick Skelton

Это то, что я искала, Ричард! Где-то, глубоко в моей нечеткой памяти, было что-то близкое к тому, что вы опубликовали выше. Я не пошел дальше, потому что меня смутили сообщения, в которых говорилось именно о той проблеме,о которой Вы упомянули, а именно о том, что клиент может привести к словарю<K, V>.

Большое спасибо!

Рейтинг:
16

Richard MacCutchan

Видеть Object.MemberwiseClone Метод (Система)[^].