Search code examples
.netwcfreadonly-collection

A ReadOnlyCollection isn't readonly. How do i create a true ReadOnlyCollection?


I'm aware that readonly collection prevents adding/removing from a list but why doesn't it prevent the setting of properties of objects in the collection.

 System.Collections.ObjectModel.ReadOnlyCollection<PersonPhoneNumber> ReadOnlyPhoneNumbers = new System.Collections.ObjectModel.ReadOnlyCollection<PersonPhoneNumber>(_PhoneNumbers);
            ReadOnlyPhoneNumbers[0].Number = "01111111111111";

For the purpose of this question assume the _PhoneNumbers is a List and it contains at least one instance of the PersonPhoneNumber class.

How do expose a collection of objects and make the objects read only? The origins of this problem stem from having to expose a private collection in a WCF data contract but i don't want the collection to be accessible.

I want to use:

  Person.Mobile = "011111111111111";

Instead of:

Person.PhoneNumbers.Add(New PersonPhoneNumber{Number= "01111111111111", Type=Mobile});

Solution

  • Since PersonPhoneNumber is a class, the ReadOnlyCollection provides you with access to the reference of any PersonPhoneNumber object. As you have the reference to the PersonPhoneNumber object, you can do anything that the PersonPhoneNumber object allows you to do and the fact that it came from a ReadOnlyCollection is not relevant.

    You could consider making PersonPhoneNumber a struct instead. If you do that then when you request the indexed object from the collection the framework will box it in order avoid copying the entire struct (for efficiency). But if you then try to modify it you will get the error "Cannot modify the result of an unboxing conversion":

    ReadOnlyPhoneNumbers[0].Number = "01111111111111";
    // Cannot modify the result of an unboxing conversion
    

    You can assign it to a local variable, but this will make a copy:

    PersonPhoneNumber ppn = ReadOnlyPhoneNumbers[0].Number;
    ppn.Number = "01111111111111";
    

    ppn is a copy. The original in the ReadOnlyCollection is unmodified.

    (Of course, before changing PersonPhoneNumber to a struct you'll need to consider the other consequences of this change. There may be other reasons that make a struct inappropriate.)