Search code examples
c#interfaceprotecteddatamember

How to have C# interface with readonly member


Interface inconvenience

I recently found myself in need of something, which should very much be possible in C# (I know it is in C++): Several classes need an api key, which absolutely has to be a private, immutable field (except for being declared in the constructor). To avoid code duplication, I wanted to create an interface for classes that need an api key.

I will let the code speak for itself:

public interface IHasApiKey
{
    protected readonly string _apiKey = String.Empty;
}

Problems:

  • I could let it be a class instead, since interfaces cannot instantiate member attributes. But since C# does not allow multiple inheritance, and since I consider this feature a behaviour rather than an implementation, I can't see why it shouldn't be an interface. And it might clash with classes which already have a base class.
  • I could convert it into a property, but no matter the accessibility level, if it is inherited, it can still be modified in methods of derived classes, whereas I really want the behaviour of readonly. (const, but can be set in the constructor)
  • I discovered the attribute System.ComponentModel.ReadOnlyAttribute, but documentation is very limited, and it doesn't look like it performs like readonly, but more like an attribute which can be queried for in user code.
  • If I convert it to an auto-property, then all derived classes need to specify a private data member to point to, which again means duplicate code (which I try to avoid by having this interface in the first place)

For completeness' sake, here is what I imagine the correct code would look like in C++:

class IHasApiKey
{
private:
    std::string _apiKey = "";
protected:
    IHasApiKey(const std::string& apiKey) : _apiKey(apiKey) {}

    // tbo, I'm not quite sure about how to optimally write this one,
    // but the idea is the same: provide protected read access.
    const std::string& GetKey() { return const_cast<std::string&>(_apiKey); }
};

Do I explain properly? And does anyone have an idea of how to solve this elegantly? Thanks a lot in advance.


Solution

  • Update [Closed]

    It seems I am limited by my choice of language. C# has no way of accomplishing what I want. The best thing would be allow decorating the interface's setter:

    public interface IHasApiKey
    {
        protected string _apiKey { get; readonly set; }
    }
    

    But likely that would require impossible changes to the compiler, and likely break with the language design. I find it unlikely that it will ever be added.

    Thank you everyone who took their time to think about this!