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

Kry*_*hic 0 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
    }
}
Run Code Online (Sandbox Code Playgroud)

我在StackOverflow上看到很多帖子说C#不支持这种行为,但我的问题是:为什么C#不支持我所描述的接口中的不可变属性?我打算做什么背后的基本设计缺陷?

SO *_*ood 9

因为接口定义了合同.当你说合同需要获取时,你说实施者必须提供获取,你不能说"你只能这样做",所以,给定:

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