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:
readonly
. (const, but can be set in the constructor) 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.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.
C# interfaces don't have a state, you can't declare field in interface non writable non read only. And it turns out that for keeping a state you need class, so in your case it should be base class, or concrete one...
One way to go is to declare a get property in interface, which will force all classes that implement this interface to provide get
public interface IHasApiKey
{
string ApiKey {get;}
}
and classes should look like this
public class SomeFoo : IHasApiKey
{
private readonly string _apiKey;
public SomeFoo(string apiKey)
{
_apiKey = apiKey;
}
public string ApiKey => _apiKey;
}
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!
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.