我刚试图实现一个不可变的接口属性后发现,C#显然不支持我正在寻找的行为.我计划的很简单,对象会订阅一个包含不可变泛型属性的接口,这意味着没有setter的属性.但是,令我惊讶的是,订阅类仍然可以添加setter而不会出现任何错误.事实上,似乎C#接口完全忽略了属性的签名.它所关心的只是属性类型和名称.
例如:
namespace Some.Arbitrary.Framework
{
public interface IIdentifiable<T>
{
/// <summary>
/// Classes that subscribe to this interface
/// may still add a 'set;' signature.
/// </summary>
T Identifier { get; } // the lack of 'set;' is ignored
}
}
Run Code Online (Sandbox Code Playgroud)
我在StackOverflow上看到很多帖子说C#不支持这种行为,但我的问题是:为什么C#不支持我所描述的接口中的不可变属性?我打算做什么背后的基本设计缺陷?
因为接口定义了合同.当你说合同需要获取时,你说实施者必须提供获取,你不能说"你只能这样做",所以,给定:
public interface IData
{
string Data { get; }
}
Run Code Online (Sandbox Code Playgroud)
你其实在说
public interface IData
{
string GetData();
}
Run Code Online (Sandbox Code Playgroud)
客户端总是可以这样做:
public class Data : IData
{
public string Data { get; set; }
}
Run Code Online (Sandbox Code Playgroud)
因为它实际上是这样做的:
public class Data : IData
{
public string GetData() {}
public void SetData(string data) {}
}
Run Code Online (Sandbox Code Playgroud)
所以,Data在关心的情况下实施IData合同IData.
您可以使用的最相似的结构是:
public interface IIdentifiable<T>
{
T Identifier { get; }
}
public abstract class IdentifiableBase<T> : IIdentifiable<T>
{
T Identifier { get; protected set; }
}
Run Code Online (Sandbox Code Playgroud)
并使你的类实现IdentifiableBase<T>,或者你可以保持IdentifiableBase类并完全抛弃接口.