为什么C#不支持接口中的不可变属性?

时间:2017-12-11 22:55:50

标签: c# interface

我刚试图实现一个不可变的接口属性后发现,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#不支持接口中的不可变属性,就像我所描述的那样?我打算做什么背后的基本设计缺陷?

1 个答案:

答案 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类并完全抛弃接口。