Given the below: Is it truly the case that if an IReadOnly(of T) was conceived from an extant MutableEquivalent(of T), that simply casting to the mutable version allows full access, and changes to an object others may rely on to have static elements/count? The output below shows my "THIRD INJECTION" string, despite iterating through a read only collection. Is it just manners and self control that prohibit casting a readonly collection down? Are you supposed to see the interface provided, and bear its restrictions, cast-invariant, due to type alone? Thanks for any clarification on what this interface and others like it truly promise/guarantee.
EDIT- This is not a duplicate of IReadOnlyCollection<T>
vs List.AsReadOnly() since I didn't mention List.AsReadOnly() in my question, nor IReadOnlyCollection. Those were introduced by responders. This was a question on underlying mutable list exposure when behind an IReadOnly interface. There are some overlaps in some comments, but a question such as "What does IReadOnly actually do for its underlying mutable List(of T)?" duplicates the spirit of my question. Not "What is the difference between these two entities pertaining to read only?", since I only mentioned one.
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"};
}
The underlying collection of READONLY
is a mutable list, this is the reason that the cast actually succeeds when creating the hack
variable. READONLY
is read-only for any of its consumers, but the underlying list can still be mutated.
UPDATED: As Sir Rufo pointed out, exposing the list by way of list.AsReadOnly()
will prevent hard casting.