Search code examples
c#immutabilityrecordmutable

Exposing an Immutable and Mutable Record Class C#


I would like to write a set of c# record classes that offer both a Immutable and Mutable version of themselves.
This is similar to how there is a List and ReadOnlyList offered in c# (yes, arguably not quite as safe as the caller can still cast to the mutable version, but I am okay with that and that is not the heart of my question)

There are a few issues that I am running into in my implementations that I've tried so far:
Implement with Interfaces

    public record class MutableRecord : IReadOnlyRecord
    {
        public int ValueTypeProperty { get; set; }

        // This is is one problem. In the Mutable Record I would like to expose the Mutable 
        // version of the other record type. As opposed to the readonly interface.

        // public OtherMutableRecord RefernceTypeProperty { get; set; }
        public IReadOnlyRecord RefernceTypeProperty { get; set; }
    }

    public interface IReadOnlyOtherRecord
    {
        int SomeData { get; }
    }

    public record class OtherMutableRecord : IReadOnlyOtherRecord
    {
        public int SomeData { get; set; }
    }

Implementation with Base Classes
I tried swapping out the above interfaces with base classes and then using the new keyword to achieve implementation hiding. But c# doesn't allow for multiple inheritance. In many cases I have classes which need to derive from the ReadOnlyBase class and the other base class (used for other operations in the code, such as storing common objects in a List). So ideally the interface implementation would be best, but I can't get around the interface requiring a specific type.


Solution

  • you can use explicit interface implementation to use expose different properties or levels of access based on the reference type:

    public record class MutableRecord : IReadOnlyRecord
    {
        public int ValueTypeProperty { get; set; }
    
        IReadOnlyOtherRecord IReadOnlyRecord.RefernceTypeProperty => ReferenceTypeProperty;
        public OtherMutableRecord ReferenceTypeProperty { get;  set;}
    }
    

    Note that "immutable" and "readonly" means slightly different things. The former implies that the object never changes, while the later that you cannot change it.