不变性的真正定义?
我想知道如何定义不变性? 如果值没有公开,那么无法修改,那就够了吗?
是否可以在类型内修改值,而不是类型的客户?
或者只能将它们设置在构造函数中? 如果是这样,在双初始化的情况下(在结构上使用this
关键字等)对于不可变类型仍然可以吗?
我怎样才能保证该类型是100%不可变的?
如果值没有公开,那么无法修改,那就够了吗?
不,因为您需要读取权限。
是否可以在类型内修改值,而不是类型的客户?
不,因为那仍然是突变。
或者只能将它们设置在构造函数中?
丁丁丁! 另外一点,不可变类型通常具有构造和返回新实例的方法,并且通常还有额外的构造函数标记为internal
专门供这些方法使用。
我怎样才能保证该类型是100%不可变的?
在.Net中获得这样的保证是很棘手的,因为你可以使用reflection来修改(变异)私有成员。
之前的海报已经说明你应该在构造函数中为你的字段赋值,然后把它们放在手上。 但这有时说起来容易做起来难。 假设您的不可变对象公开了List
类型的属性。 该列表是否允许更改? 如果没有,你将如何控制它?
Eric Lippert在他的博客中写了一系列关于C#不变性的post,你可能会感兴趣: 你在这里找到了第一部分 。
我认为在所有这些答案中可能会遗漏的一件事是,我认为即使内部状态发生变化,对象也可以被认为是不可变的 – 只要这些内部变更对’客户’代码不可见。
例如, System.String
类是不可变的,但我认为允许缓存实例的哈希代码,因此哈希仅在第一次调用GetHashCode()
。 请注意,据我所知, System.String
类不会这样做,但我认为它可以并且仍然被认为是不可变的。 当然,任何这些更改都必须以线程安全的方式处理(与更改的不可观察方面一致)。
说实话,我想不出有很多可能需要或者需要这种“看不见的可变性”的理由。
以下是维基百科的不变性定义( 链接 )
“在面向对象和函数式编程中,不可变对象是一个对象,其状态在创建后无法修改。”
基本上,一旦创建了对象,就不能改变它的任何属性。 一个例子是String类。 创建String对象后,无法更改。 对它执行的任何操作实际上都会创建一个新的String对象。
那里有很多问题。 我会尝试单独回答每个问题:
希望有所帮助。
我已经了解到,不可变性是指在构造函数中设置所有内容并且在对象的生命周期内不能稍后修改它。
不变性的定义可以在Google上找到 。
例:
不可变的 – 字面意思是,无法改变。
https://www.filosofia.net/materiales/rec/glosaen.htm
就不可变数据结构而言,典型定义是一次写入多次读取,换句话说,正如您所说,一旦创建,它就无法更改。
有些情况略微处于灰色区域。 例如,.NET字符串被认为是不可变的,因为它们无法更改,但是,StringBuilder在内部修改了String对象。
不可变的本质上是一个强迫自己在自己的代码中成为最终的类。 一旦它在那里,什么都不能改变。 据我所知,事情是在构造函数中设置的,然后就是这样。 我不知道其他东西怎么可能是不可变的。
不幸的是,在c#/ vb.net中没有不可变的关键字,虽然它已被争论,但是如果没有autoproperties并且所有字段都用readonly声明(readonly字段只能在构造函数中分配)modfier并且所有字段都被声明为一个不可改变的类型,你将确保自己的不变性。
不可变对象是一种可观察状态永远不会被任何合理的代码执行序列改变的对象。 不可变类型是一种保证暴露给外部世界的任何实例都是不可变的类型(这个要求通常被声明为要求对象的状态只能在其构造函数中设置;对于具有对象的对象,这不是绝对必要的私有构造函数,对于在构造期间调用外部方法的对象也不够。
然而,其他答案忽略的一点是对象状态的定义。 如果Foo
是一个类,则List
的状态由其中包含的对象标识序列组成。 如果对特定List
实例的唯一引用由代码保存,既不会导致更改该序列,也不会将其公开给可能执行此操作的代码,那么该实例将是不可变的,无论Foo
对象是否引用其中是可变的或不可改变的。
使用类比,如果有一个汽车VIN列表(车辆识别号码)打印在防篡改纸上,列表本身将是不可变的,即使汽车不是。 即使列表今天包含十辆红色汽车,明天也可能包含十辆蓝色汽车; 然而,它们仍然是十辆汽车 。
上述就是C#学习教程:不变性的真正定义?分享的全部内容,如果对大家有所用处且需要了解更多关于C#学习教程,希望大家多多关注—计算机技术网(www.ctvol.com)!
本文来自网络收集,不代表计算机技术网立场,如涉及侵权请联系管理员删除。
ctvol管理联系方式QQ:251552304
本文章地址:https://www.ctvol.com/cdevelopment/949895.html