Каковы недостатки этого шаблона для обеспечения неизменности?

Учитывая следующий класс:

public static class ComboModel
{
    public static Dictionary<int, int[]> Items()
    {
        return new Dictionary<int, int[]>
        {
            {
                1, 
                new[] { 
                    2,
                    3,
                    4  
                }
            }
        };
    }
}

Я хочу обеспечить неизменность данных в классе, но это похоже на javascript-y и вызвало некоторую смутную (но сильную) критику со стороны моих сверстников. Что с этим не так?

1 ответ

Просто используйте ReadOnlyDictionary и выделите его только один раз:

public static class ComboModel {
    private static readonly ReadOnlyDictionary<int, int[]> _items = new ReadOnlyDictionary<int, int[]>(new Dictionary<int, int[]> {
        {
            1,
            new[] {
                2,
                3,
                4
            }
        }
    });

    public static IReadOnlyDictionary<int, int[]> Items
    {
        get { return _items; }
    }
}

Обратите внимание, что вы не только выделяете новый экземпляр для каждого вызова, как уже упоминалось ранее, - вы также даете неверное представление вызывающему абоненту, что он может изменить этот словарь. В ReadOnlyDictionary нет методов, которые могут его изменить. Есть и другие преимущества, когда вызывающий объект знает, что структура, которую он получил, не может быть изменена: например, он может безопасно обрабатывать элементы там с несколькими потоками.

Обновление: конечно, коллекции только для чтения волшебным образом не делают объекты, хранящиеся в этих коллекциях, доступными только для чтения - только сама коллекция. Если вы хотите обеспечить неизменность массивов int[] в вашем примере, просто сделайте их также только для чтения:

public static class ComboModel {
    private static readonly IReadOnlyDictionary<int, ReadOnlyCollection<int>> _items = new ReadOnlyDictionary<int, ReadOnlyCollection<int>>(new Dictionary<int, ReadOnlyCollection<int>> {
        {
            1,
            Array.AsReadOnly(new[] {
                2,
                3,
                4
            })
        }
    });

    public static IReadOnlyDictionary<int, ReadOnlyCollection<int>> Items
    {
        get { return _items; }
    }
}
Другие вопросы по тегам