如何让只读成员具有 C# 接口
How to have C# interface with readonly member
界面不便
我最近发现自己需要一些东西,这在 C# 中应该很有可能(我知道它在 C++ 中):几个 classes 需要一个 api 键,它绝对有成为私有的、不可变的字段(在构造函数中声明的除外)。为了避免代码重复,我想为需要 api 键的 classes 创建一个接口。
我会让代码自己说话:
public interface IHasApiKey
{
protected readonly string _apiKey = String.Empty;
}
问题:
- 我可以让它成为 class,因为接口不能实例化成员属性。但由于 C# 不允许多重继承,并且由于我认为此功能是一种行为而不是一种实现,所以我不明白为什么它不应该是一个接口。它可能会与已经有基础 class.
的 classes 发生冲突
- 我可以将它转换成属性,但无论可访问性级别如何,如果它是继承的,它仍然可以在派生的方法中修改classes,而我真的想要
readonly
的行为。 (常量,但可以在构造函数中设置)
- 我发现了属性
System.ComponentModel.ReadOnlyAttribute
,但是文档非常有限,而且看起来不像 readonly
那样执行,而更像是可以在用户代码中查询的属性.
- 如果我将它转换为自动 属性,那么所有派生的 classes 都需要指定一个私有数据成员指向,这又意味着重复代码(我尽量避免通过首先拥有这个界面)
为了完整起见,以下是我想象中的正确代码在 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); }
};
我解释得当吗?有没有人知道如何优雅地解决这个问题?
非常感谢。
C# 接口没有状态,您不能在接口中声明字段不可写非只读。事实证明,要保持状态,您需要 class,因此在您的情况下,它应该是基础 class,或具体的...
一种方法是在接口中声明一个get 属性,这将强制所有实现此接口的classes提供get
public interface IHasApiKey
{
string ApiKey {get;}
}
和classes应该是这样的
public class SomeFoo : IHasApiKey
{
private readonly string _apiKey;
public SomeFoo(string apiKey)
{
_apiKey = apiKey;
}
public string ApiKey => _apiKey;
}
更新[关闭]
看来我的语言选择有限。 C# 无法完成我想要的。最好的办法是允许装饰界面的 setter:
public interface IHasApiKey
{
protected string _apiKey { get; readonly set; }
}
但这可能需要对编译器进行不可能的更改,并且可能会破坏语言设计。我发现它不太可能被添加。
感谢所有花时间思考这个问题的人!
界面不便
我最近发现自己需要一些东西,这在 C# 中应该很有可能(我知道它在 C++ 中):几个 classes 需要一个 api 键,它绝对有成为私有的、不可变的字段(在构造函数中声明的除外)。为了避免代码重复,我想为需要 api 键的 classes 创建一个接口。
我会让代码自己说话:
public interface IHasApiKey
{
protected readonly string _apiKey = String.Empty;
}
问题:
- 我可以让它成为 class,因为接口不能实例化成员属性。但由于 C# 不允许多重继承,并且由于我认为此功能是一种行为而不是一种实现,所以我不明白为什么它不应该是一个接口。它可能会与已经有基础 class. 的 classes 发生冲突
- 我可以将它转换成属性,但无论可访问性级别如何,如果它是继承的,它仍然可以在派生的方法中修改classes,而我真的想要
readonly
的行为。 (常量,但可以在构造函数中设置) - 我发现了属性
System.ComponentModel.ReadOnlyAttribute
,但是文档非常有限,而且看起来不像readonly
那样执行,而更像是可以在用户代码中查询的属性. - 如果我将它转换为自动 属性,那么所有派生的 classes 都需要指定一个私有数据成员指向,这又意味着重复代码(我尽量避免通过首先拥有这个界面)
为了完整起见,以下是我想象中的正确代码在 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); }
};
我解释得当吗?有没有人知道如何优雅地解决这个问题? 非常感谢。
C# 接口没有状态,您不能在接口中声明字段不可写非只读。事实证明,要保持状态,您需要 class,因此在您的情况下,它应该是基础 class,或具体的...
一种方法是在接口中声明一个get 属性,这将强制所有实现此接口的classes提供get
public interface IHasApiKey
{
string ApiKey {get;}
}
和classes应该是这样的
public class SomeFoo : IHasApiKey
{
private readonly string _apiKey;
public SomeFoo(string apiKey)
{
_apiKey = apiKey;
}
public string ApiKey => _apiKey;
}
更新[关闭]
看来我的语言选择有限。 C# 无法完成我想要的。最好的办法是允许装饰界面的 setter:
public interface IHasApiKey
{
protected string _apiKey { get; readonly set; }
}
但这可能需要对编译器进行不可能的更改,并且可能会破坏语言设计。我发现它不太可能被添加。
感谢所有花时间思考这个问题的人!