Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/.net/25.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 不变性的真正定义是什么?_C#_.net_Immutability - Fatal编程技术网

C# 不变性的真正定义是什么?

C# 不变性的真正定义是什么?,c#,.net,immutability,C#,.net,Immutability,我想知道不变性是如何定义的?如果这些值不是公开的,所以不能修改,那么就足够了 值是否可以在类型内部修改,而不是由类型的客户修改 或者只能在构造函数中设置它们?如果是这样,在双重初始化的情况下(在结构上使用this关键字等),对于不可变类型仍然可以吗 我如何保证类型是100%不变的 如果这些值不是公开的,所以不能修改,那么就足够了 不,因为您需要读取权限 值是否可以在类型内部修改,而不是由类型的客户修改 不,因为那还是变异 或者只能在构造函数中设置它们 叮叮!另外一点是,不可变类型通常具有构造和返

我想知道不变性是如何定义的?如果这些值不是公开的,所以不能修改,那么就足够了

值是否可以在类型内部修改,而不是由类型的客户修改

或者只能在构造函数中设置它们?如果是这样,在双重初始化的情况下(在结构上使用
this
关键字等),对于不可变类型仍然可以吗

我如何保证类型是100%不变的

如果这些值不是公开的,所以不能修改,那么就足够了

不,因为您需要读取权限

值是否可以在类型内部修改,而不是由类型的客户修改

不,因为那还是变异

或者只能在构造函数中设置它们

叮叮!另外一点是,不可变类型通常具有构造和返回新实例的方法,并且通常具有标记为
internal
的额外构造函数,专门供这些方法使用

我如何保证类型是100%不变的


在.Net中,获得这样的保证是很困难的,因为您可以使用反射来修改(变异)私有成员。

以下是Wikipedia()中对不变性的定义

在面向对象和函数式编程中,不可变对象是一个在创建后状态无法修改的对象


本质上,一旦对象被创建,它的任何属性都不能更改。String类就是一个例子。一旦创建了字符串对象,就不能对其进行更改。对它执行的任何操作实际上都会创建一个新的字符串对象。

我了解到,不可变性是指在构造函数中设置了所有内容,并且在对象的生命周期中无法在以后修改它。

不可变性的定义可以在上找到

例如:

不可变-字面意思是不能改变。
www.filosofia.net/materiales/rec/glosaen.htm

就不可变的数据结构而言,典型的定义是一次写入多次读取,换句话说,正如您所说,一旦创建,就无法更改


有些病例略呈灰色区域。例如,.NET字符串被认为是不可变的,因为它们不能更改,但是StringBuilder会在内部修改字符串对象。

不可变的本质上是一个类,它强制自己在自己的代码中成为final。一旦它存在,什么都不能改变。据我所知,事情都是在构造函数中设置的,就这样。我看不出有什么东西是不可改变的。

这里有很多问题。我将尝试逐一回答以下问题:

  • “我想知道不变性是如何定义的?”——直接来自于(一个非常准确/简洁的定义)

    不可变对象是其状态在创建后无法修改的对象

  • “如果这些值未公开为公共,因此无法修改,那么就足够了?”-不完全足够。它不能以任何方式被修改,所以你必须确保方法/函数不会改变对象的状态,如果执行操作,总是返回一个新实例

  • “是否可以在类型内部修改值,而不是由类型的客户修改?”-从技术上讲,不能在类型内部或由类型的使用者修改值。在实践中,诸如
    System.String
    (这是一种参考类型)之类的类型几乎在所有实际用途中都可以被认为是可变的,尽管在理论上不是这样

  • “或者只能在构造函数中设置它们?”-是的,理论上,这是唯一可以设置状态(变量)的地方

  • “如果是这样,在双重初始化的情况下(在结构上使用this关键字等),对于不可变类型仍然可以吗?”-是的,这仍然很好,因为它是初始化(创建)过程的一部分,并且在完成之前不会返回实例

  • “我如何保证类型是100%不可变的?”-以下条件应确保这一点。(如果我遗漏了一个,请有人指出。)

  • 不要暴露任何变量。它们都应该保持
    私有
    (即使
    受保护
    也不能接受,因为派生类可以修改状态)
  • 不允许任何实例方法修改状态(变量)。这应该只在构造函数中完成,而如果方法需要返回“修改的”对象,则应该使用特定构造函数创建新实例
  • 暴露(只读)的所有成员或方法返回的对象本身必须是不可变的
  • 注意:您不能确保派生类型的不变性,因为它们可以定义新的变量。这就是为什么要标记任何不希望的类型,以确保它是不可变的,即
    密封的
    ,以便在代码中的任何地方都不能将派生类视为基本不可变类型


希望这能有所帮助。

之前的海报已经说明,您应该在构造函数中为字段赋值,然后不要插手。但这有时说起来容易做起来难。假设您的不可变对象公开了类型为
List
的属性。这个名单允许改变吗?如果没有,你将如何控制它


Eric Lippert在他的博客中写了一系列关于C#不变性的文章,你可能会发现这很有趣:。

我认为在所有这些答案中可能遗漏的一件事是,我认为一个对象可以被认为是不可变的,即使它的内部状态发生了变化——只要那些内部变化对“客户机”不可见代码

例如,
System.String
类是不可变的,但我认为它可以缓存实例的哈希代码,因此哈希值仅在第一次调用
GetHashCode()
时计算。请注意,据我所知