我们知道不变性的概念,但需要知道除
之外的一些不可变类型还有更多吗?
答案 0 :(得分:12)
框架类库中的不可变类型列表如下所示。 (随意扩展它!)
System.…
Byte
和SByte
Int16
和UInt16
Int32
和UInt32
Int64
和UInt64
IntPtr
Single
Double
Decimal
new { ... }
,在VB.NET中为New With { ... }
)enum
,Enum
)obj.PropertyChanged += callback
之类的操作,但实际上obj.PropertyChanged
引用已变异为指向到新构造的委托实例;原始委托实例保持不变。) DateTime
,TimeSpan
(在this answer中提及)和DateTimeOffset
DBNull
Guid
Nullable<T>
String
Tuple<…>
类型(在this answer中提到) Uri
Version
Void
System.Linq.…
Lookup<TKey, TElement>
答案 1 :(得分:1)
TimeSpan
或现代型家庭Tuple
。 Tuple
是不可变的,因为它实现了支持.NET中的函数式语言(F#f.e.)。
当然,您可以根据需要将自己的类和结构变为可变或不可变。不可变类型(也称为值对象)在多线程编程,函数编程中用于清除代码。
要使类或结构不可变,只需删除所有public / protected / internal setter;并且最好使用readonly
关键字声明所有字段。
答案 2 :(得分:1)
我不确定您是否正在寻找.NET中的公共不可变类型或完全不可变的类型。此外,您只想处理.NET中的公共类型?更深层次的问题是定义什么形成不变性。是否只有
的班级public readonly int[] Numbers;
让它一成不变?数字本身不能改变,但其内容可以改变。你明白了。
无论如何,您可以通过编程方式检查自己 。对于更深层次的嵌套检查,您将需要递归(我不会在这里做)
加载您想要检查的所有程序集,并执行类似(未测试)
之类的操作var immutables = AppDomain.CurrentDomain
.GetAssemblies()
.SelectMany(t => t.GetTypes())
.Where(t => t
.GetProperties(your binding flags depending on your definition)
.All(p => !p.CanWrite)
&& t
.GetFields(your binding flags depending on your definition)
.All(f => f.IsInitOnly)
.ToList();
即使这样也不足以找到集合类型的不变性。一些不可变的集合类型(虽然不是默认.NET核心的一部分)可以在这里找到:Immutable Collections
一些值得注意的不可变因素:
String
,Tuple
,匿名类型不可变的集合类型,如
ImmutableArray(预发行版)
ImmutableDictionary
ImmutableSortedDictionary
ImmutableHashSet
ImmutableList
ImmutableQueue
ImmutableSortedSet
ImmutableStack
答案 3 :(得分:0)
mscorlib :
中的一些示例decimal
(U)IntPtr
DateTime
,DateTimeOffset
,TimeSpan
KeyValuePair<,>
- 相反,DictionaryEntry
不是不可变的Tuple<...>
(Multicast)Delegate
- 与字符串类似,在更改时总是会返回一个新实例。Guid
Version
有趣的是,string
实际上并不是真正不可改变的;但是,我们可以将其视为“几乎不可变”的类型,这意味着,不能通过公共方式(至少在安全的上下文中)更改字符串实例的内容。但它有一个wstrcpy
内部方法,StringBuilder
类用它来操作字符串实例。
答案 4 :(得分:-1)
在.NET 5和新的C#9.0版本中,几乎每个对象现在都可以不可变(或在属性中包含不可变状态)
此处有更多相关信息:https://martinstanik.com/2020/10/09/immutable-data-types-after-net-5-release/