2016-09-02 2 views
-1

Я рассматриваю три подхода для возврата ссылок на внутренние экземпляры Dictionary (C#) в отношении безопасности кода и влияния на читаемость кода визуально для проекта, над которым я работаю.C#, возвращающий словарные ссылки безопасно

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

1) Используйте второй ReadOnlyDictionary экземпляр, чтобы обернуть внутренний словарь, только когда-либо позволить ReadOnlyDictionary избежать класс:

2) Возвращение словаря экземпляра как IReadOnlyDictionary, но переделывая позволит ему быть изменен так не безопасен, как вариант №1 или №3.

3) Возвращение Dictionary.ToImmutableDictionary() как ImmutableDictionary, когда она сбегает вмещающий класс так, что возвращаемый объект является непреложным видом внутреннего словаря, хотя это будет сделать новую копию для каждого вызова подвергаясь выше стоимость, это должно быть хорошо с небольшими простыми словарями (которые мои).

private readonly Dictionary<string, string> innerDictionary = new Dictionary<string, string>(); 

    // Only required for Example #1 
    private readonly IReadOnlyDictionary<string, string> readonlyInnerDictionary; 

    public ExampleClass() { 
     // Only required for Example #1 
     readonlyInnerDictionary = new ReadOnlyDictionary<string, string>(innerDictionary); 
    } 

    public IReadOnlyDictionary<string, string> GetExampleOne() { 
     // Requires a second dictionary which is more boiler plate but the object being returned is truly readonly 
     return readonlyInnerDictionary;  
    } 

    public IReadOnlyDictionary<string, string> GetExampleTwo() { 
     // Requires InnerDictionary be defined as Dictionary (Not IDictionary) but doesn't require the second dictionary be defined 
     // which is less boiler plate, but the object returned could be re-cast to it's mutable form meaning it's not truly mutation safe. 
     return innerDictionary; 
    } 

    public ImmutableDictionary<string, string> GetExampleThree() { 
     // Truly immutable object returned, but a new instance is built for every call; fortunately all of my dictionaries are small (containing at most 9 keys) 
     return innerDictionary.ToImmutableDictionary(); 
    } 

ответ

0

Определено, что самый простой, простой и безопасный; но не самое эффективное решение состоит в том, чтобы внутренне использовать ConcurrentDictionary, который обеспечивает безопасность потока (от System.Collections.Concurrent), а затем для использования System.Collections.Immutable для вызова dictionary.ToImmutableDictionary(), который создает словарь, который выходит из внутреннего класса. Подпись интерфейса - ImmutableDictionary<KeyType, ValueType>.

Это не самое эффективное решение, но в моем случае со словарями с менее чем 12 ключами и небольшими простыми объектами, представляющими состояние в большинстве случаев, что не вызывает беспокойства.

1

Вариант 1 - это путь. Вы можете переделать ReadOnlyDictionary в IDictionary, но это будет сгенерировано исключение при попытке мутировать:

void CastingTest() 
     { 
      var dic1 = new Dictionary<string, string>(); 
      dic1.Add("Key", "Value"); 
      var dic2 = new ReadOnlyDictionary<string, string>(dic1); 
      var castedDic = (IDictionary<string, string>)dic2; 
      castedDic.Add("AnotherKey", "Another Value"); //System.NotSupportedException, Collection is read only 
     } 

ReadOnlyDictionary не создает другой словарь. Он указывает на ту же ссылку, что и первая, инкапсулируя ее. Так что, если вы это сделаете:

void AddTest() 
     { 
      var dic1 = new Dictionary<string, string>(); 
      dic1.Add("Key", "Value"); 
      var dic2 = new ReadOnlyDictionary<string, string>(dic1); 
      dic1.Add("Key2", "Value2"); //Now dic2 have 2 values too. 
     } 

Никогда не подвергайте свою внутреннюю книгу, и со мной все будет в порядке.

+0

@Syntax Решили ли вы ваши сомнения? Я могу поделиться более подробной информацией, если вы хотите. –

+0

Извините за задержку Артура, ваш отзыв был очень полезен для дальнейшего обсуждения, однако я нашел другое решение, которое я предпочел больше, обсудив это дальше с друзьями; для всех, кого это интересует, я представил его как ответ на мой собственный вопрос и отметил его как принятый. – Syntax

+0

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

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