我刚试图实现一个不可变的接口属性后发现,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
}
}
我在StackOverflow上看到很多帖子说C#不支持这种行为,但我的问题是:为什么C#不支持接口中的不可变属性,就像我所描述的那样?我打算做什么背后的基本设计缺陷?
答案 0 :(得分:9)
因为接口定义了合同。当你说合同需要get时,你说实现者必须提供get,你不能说“你只能这样做”,所以,给定:
public interface IData
{
string Data { get; }
}
你实际上在说
public interface IData
{
string GetData();
}
客户端总是可以这样做:
public class Data : IData
{
public string Data { get; set; }
}
因为它实际上是这样做的:
public class Data : IData
{
public string GetData() {}
public void SetData(string data) {}
}
因此,Data
实施IData
合约,只要IData
关注。
您可以使用的最相似的结构是:
public interface IIdentifiable<T>
{
T Identifier { get; }
}
public abstract class IdentifiableBase<T> : IIdentifiable<T>
{
T Identifier { get; protected set; }
}
让你的类实现IdentifiableBase<T>
,或者你可以保留IdentifiableBase
类并完全抛弃接口。