【发布时间】:2020-05-28 00:06:00
【问题描述】:
界面不便
我最近发现自己需要一些东西,这在 C# 中应该很有可能(我知道它在 C++ 中):几个类需要一个 api 密钥,它绝对必须是一个私有的、不可变的字段(除了在构造函数中声明)。为了避免代码重复,我想为需要 api 密钥的类创建一个接口。
我会让代码自己说话:
public interface IHasApiKey
{
protected readonly string _apiKey = String.Empty;
}
问题:
- 我可以让它成为一个类,因为接口不能实例化成员属性。但是由于 C# 不允许多重继承,而且我认为这个特性是一种行为而不是一种实现,所以我不明白为什么它不应该是一个接口。而且它可能会与已经有基类的类发生冲突。
- 我可以将其转换为属性,但无论可访问性级别如何,如果它是继承的,它仍然可以在派生类的方法中进行修改,而我真的想要@987654322的行为@。 (常量,但可以在构造函数中设置)
- 我发现了属性
System.ComponentModel.ReadOnlyAttribute,但是文档非常有限,而且它看起来不像readonly那样执行,而更像是一个可以在用户代码中查询的属性。 - 如果我将其转换为自动属性,则所有派生类都需要指定要指向的私有数据成员,这再次意味着重复代码(我首先尝试通过使用此接口来避免这种情况)李>
为了完整起见,以下是我想象的 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# 中,接口是一个特定的东西,它只规定 clients 可以对实例做什么。它永远不能规定暴露接口的类应该如何实现它。从这个意义上说,“考虑”行为并不取决于您。这确实意味着您需要一个基类来强制执行这一点,如果一个类不喜欢从它继承,它就必须重新实现。如果不希望这样做,您可以使用封装和
sealed。 -
"如果我将它转换为自动属性,那么所有派生类都需要指定一个私有数据成员指向,这再次意味着重复代码(我试图通过在这个接口中避免这种情况)第一名)” - 为什么不呢?您可以拥有只有 getter 的属性,这不会使其在 readonly 方面完全只读,但它将具有私有 setter。如果您想保留界面,则可以最接近它。所有属性的使用都会最大限度地在编译时给你警告。
-
不要在问题中添加答案。只需发布您自己的答案或接受另一个答案。
-
你能不能至少让我自己删除答案,现在我需要再写一遍.. :)
-
您只需点击上面的“已编辑 # 分钟前”链接即可查看您发布的帖子,然后将其复制/粘贴到答案中。
标签: c# interface protected datamember