Защита C# IReadOnlyList<t> мгновенно подрывается унынием или я что-то упустил?
Учитывая следующее: действительно ли это так, что если IReadOnly(из T) был задуман из существующего MutableEquivalent(из T), то простое приведение к изменяемой версии обеспечивает полный доступ, и изменения в объекте, на которые могут полагаться другие статические элементы / количество? Вывод ниже показывает мою строку "THIRD INJECTION", несмотря на итерацию по коллекции только для чтения. Это просто манеры и самоконтроль, которые запрещают бросать коллекцию только для чтения? Предполагается ли, что вы видите предоставленный интерфейс и несете его ограничения, лить-инвариантные, только из-за типа? Спасибо за любые разъяснения о том, что этот интерфейс и другие, как он, действительно обещают / гарантируют.
РЕДАКТИРОВАТЬ - это не дубликат IReadOnlyCollection<T>
vs List.AsReadOnly(), так как я не упомянул List.AsReadOnly() в моем вопросе, ни IReadOnlyCollection. Они были представлены респондентами. Это был вопрос о подверженности изменчивому списку за интерфейсом IReadOnly. В некоторых комментариях есть некоторые совпадения, но такой вопрос, как "Что на самом деле делает IReadOnly для своего базового изменяемого списка (T)?" дублирует дух моего вопроса. Не "В чем разница между этими двумя объектами, имеющими отношение только к чтению?", Поскольку я упомянул только одну.
static class Program
{
public static void Main()
{
List<string> hack = (List<string>) READONLY;
hack.Add("THIRD INJECTION");
foreach (var s in READONLY)
{
Console.WriteLine(s);
}
}
public static readonly IReadOnlyList<string> READONLY = new List<string>{"@0", "@1"};
}
2 ответа
Основная коллекция READONLY
изменяемый список, это причина того, что приведение hack
переменная. READONLY
только для чтения для любого из его потребителей, но основной список все еще может быть изменен.
ОБНОВЛЕНО: Как указал сэр Руфо, разоблачая список list.AsReadOnly()
предотвратит жесткое литье.
Я не осознавал, что интерфейс был скорее слабой защитой для программиста, чем "постоянным" барьером для мутации. … Я неправильно предположил, что переход от readonly к mutable будет неверным.
Интерфейс вообще не предназначен для "защиты". Это просто обещание реализовать определенные функции.
Преимущество IReadOnlyList<T>
является одной из семантики и теперь, с универсальной дисперсией типа в C#, гибкость. Семантическая выгода позволяет вам выставлять список таким образом, который выражает намерение только читать его, а не изменять его.
Гибкость приходит, потому что параметр типа может быть сделан ковариантным. Это позволяет неявные преобразования из IReadOnlyList<T1>
в IReadOnlyList<T2>
где T1
наследуется T2
,
Разработчик интерфейса должен решить, обеспечена ли истинная неизменность или нет. Если вы хотите, чтобы коллекция была действительно неизменной, вы должны использовать ReadOnlyCollection<T>
в качестве реализации для IReadOnlyList<T>
, вместо List<T>
, Вы можете передать любой IList<T>
реализация к ReadOnlyCollection<T>
конструктор, и новый объект представит, что IList<T>
данные объекта, не допуская изменения (напрямую… вы, конечно, всегда можете обмануть с помощью отражения, даже с объектом, который действительно неизменен, а не просто как обертка ReadOnlyCollection<T>
).
С любым интерфейсом вы всегда имеете дело только с конкретным объектом, который имеет определенный тип, этот тип всегда реализует некоторую функциональность и всегда может быть приведен к исходному типу, а также любым другим интерфейсам, которые он может реализовать.
Было бы ошибкой считать интерфейсы каким-либо существенным способом защиты. Это не так. Они просто выражают, на что способен объект.