C#中如何保证不可变性

7
阅读了关于C#中不变性的很多内容,并理解它的好处(无副作用、安全的字典键、多线程...)后,我想到了一个问题:
为什么C#中没有一个关键词来断言一个类(或结构体)是不可变的?这个关键词应该在编译时检查,确保没有任何方式可以修改类(或结构体)。例如:
public immutable class MyImmutableClass
{
    public readonly string field;

    public string field2; //This would be a compile time error

    public readonly AnyMutableType field3; //This would be a compile time error


    public string Prop { get; }

    public string Prop2 { get; set; } //This would be a compile time error

    public AnyMutableType Prop3 { get; } //This would be a compile time error
}

我认为编译器的工作相当简单,因为它只需要检查以下几个方面:
- 所有公共字段均为只读。 - 所有公共属性仅具有 getter 方法。 - 所有公共字段或属性也具有不可变类型(简单值类型或不可变类/结构)。 - 所有公共函数或公共属性 getter 仅依赖于不可变字段或属性(如前所述的公共字段/属性,或符合相同限制的私有字段/属性)。当然,这包括 Equals()、GetHashCode() 和 ToString()。
这种设计可能存在一些问题:
- 编译器要知道编译类/结构是否不可变,可能需要在中间语言中进行更改。 - 只读泛型集合(例如IEnumerable)的不可变性将取决于类型的不可变性。所提议的immutable关键字在此情况下无用,因为即使IEnumerable是不可变的,您也不能声明它是不可变的。
这些原因足以说明该关键字不存在吗? 我是否忽略了其他缺点? 对于语言的大幅度更改,这是否仅仅不够必要?

3
这个链接是关于不可变类型的提案。 - Damien_The_Unbeliever
2
@Damien_The_Unbeliever 我认为那个不太可能,但是有一个“readonly struct”提案正在由“readonly ref”相关内容推动,很可能会在C# 7.x中实现。 - Marc Gravell
@MarcGravell - 我想那可能是我半记得的那个,但我的不可变搜索找到了我链接的那个。 - Damien_The_Unbeliever
8
该死,我本来要发表一个回答的;但我已经将其转储到了 gist 中,那里可能有一些有趣的信息:https://gist.github.com/mgravell/03dcf34005945fa494998c089e7246a5;值得一提的是,因为这里确实有上下文,所以我不同意它是纯粹基于个人观点的 - 但我不会投票再次开放,因为我的投票是自动绑定的... - Marc Gravell
1
谢谢提供信息!C#7中肯定有很棒的东西。结构体中的不可变性将是非常棒的。我也不明白为什么这个问题会是基于观点的,如果有人能帮助我改进问题... - Daniel García Rubio
我们还可以添加 public singleton class MySingletonClass 或类似 public dto class MyDTOClass 的内容。 - Fabjan
1个回答

4
简短的回答是:因为没有人提出、规定、设计、实现、测试、文档化、翻译和支持该功能。
更长的回答涉及为什么要这样做,考虑到可以通过只读字段间接实现——它会增加什么好处。
对于类来说,这似乎相对较小。请注意,有一个 [ImmutableObject(true)] 属性可供使用,但没有任何功能或框架真正需要它,因此...没有人使用它。
曾经有一个提议在C#的未来版本中添加"readonly structs"(与 ref locals, Span<T> 等相关) - 但是:它已经死了并消失了。然而,ref readonly 的东西仍然存在,它旨在防止在 struct 实例方法中重新分配 this。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接