. net中不可变类型的例子
本文关键字:类型 不可变 net | 更新日期: 2023-09-27 18:05:27
我们知道不可变的概念,但除了
,我们还需要知道一些不可变类型- 字符串
- DateTime
还有吗?
框架类库中的不可变类型列表如下:(请随意扩展!)
System.…
- 所有原始值类型:(注意:不是所有的值类型都是不可变的!)
-
Byte
和SByte
-
Int16
和UInt16
-
Int32
和UInt32
-
Int64
和UInt64
-
IntPtr
-
Single
-
Double
-
-
Decimal
-
编译器创建的所有匿名类型(c#中的(错误的原因有两个:这些类型不在FCL中,显然是VB。. NET类型是可变的)new { ... }
, VB.NET中的New With { ... }
) - 所有枚举类型(
enum
,Enum
) - 所有委托类型。(参见这个答案)。虽然看起来委托是可变的(因为你可以做像
obj.PropertyChanged += callback
这样的事情),但实际上obj.PropertyChanged
引用被突变为指向新构建的委托实例; -
DateTime
,TimeSpan
(在这个回答中提到)和DateTimeOffset
-
DBNull
-
Guid
-
Nullable<T>
-
String
- .NET 4 引入的
Tuple<…>
类型(在这个回答中提到) -
Uri
-
Version
-
Void
System.Linq.…
-
Lookup<TKey, TElement>
我不确定你是在寻找。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核心的一部分)可以在这里找到:不可变集合
一些值得注意的不可变变量:
- 一些类类型,如
String
,Tuple
,匿名类型 - 大多数结构体(值得注意的例外包括大多数枚举器)
- 枚举 代表
不可变集合类型,如
ImmutableArray(预发布版本)
ImmutableDictionary
ImmutableSortedDictionary
ImmutableHashSet
ImmutableList
ImmutableQueue
ImmutableSortedSet
ImmutableStack
TimeSpan
,或现代字体家族Tuple
。Tuple
是不可变的,因为它是为了支持。net中的函数式语言而实现的。
当然,你可以让你自己的类和结构变或不可变,如你所愿。不可变类型(又名值对象)在多线程编程、函数式编程中非常有用,可以清除代码。
要使类或结构不可变,只需删除所有public/protected/internal setter;最好使用readonly
关键字声明所有字段
一些来自mscorlib:
的例子- 所有基本类型
- 枚举
-
decimal
-
(U)IntPtr
-
DateTime
,DateTimeOffset
,TimeSpan
-
KeyValuePair<,>
-相反,DictionaryEntry
不是不可变的 -
Tuple<...>
-
(Multicast)Delegate
-与字符串类似,当它被改变时总是返回一个新的实例。 -
Guid
-
Version
string
实际上并不是不可变的;但是,我们可以将其视为"实际上不可变"的类型,这意味着字符串实例的内容不能通过公共方式更改(至少在安全上下文中是这样)。但是它有一个wstrcpy
内部方法,StringBuilder
类使用它来操作字符串实例。
在。net 5和新的c# 9.0版本中,几乎每个对象现在都可以不可变了(或者在属性中包含不可变状态)
更多信息请访问:https://martinstanik.com/2020/10/09/immutable-data-types-after-net-5-release/