.Net中不可变类型的示例
我们知道不变性的概念,但除了需要知道几个不可变类型
- 串
- 约会时间
还有更多吗?
下面是框架类库中的不可变类型列表。 (随意扩展它!)
System.…
- 所有原始值类型:( 注意: 并非所有值类型都是不可变的 !)
-
Byte
和SByte
-
Int16
和UInt16
-
Int32
和UInt32
-
Int64
和UInt64
-
IntPtr
-
Single
-
Double
-
-
Decimal
-
编译器创建的所有匿名类型(C#中的(错误有两个原因:这些类型不在FCL中,显然VB.NET类型是可变的。)New With { ... }
,VB.NET中的New With { ... }
- 所有枚举类型(
enum
,Enum
) - 所有代表类型。 (看到这个答案 。虽然看起来委托是可变的(因为你可以做像
obj.PropertyChanged += callback
这样的事情,它实际上是obj.PropertyChanged
引用,它被变异指向一个新构造的委托实例;原始委托实例保持不变。) -
DateTime
,TimeSpan
(在本回答中提到)和DateTimeOffset
-
DBNull
-
Guid
-
Nullable
-
String
- .NET 4引入的
Tuple<…>
类型(在本回答中提到) -
Uri
-
Version
-
Void
System.Linq.…
-
Lookup
TimeSpan
,或现代型家庭Tuple
。 Tuple
是不可变的,因为它实现了支持.NET中的函数式语言(F#fe)。
当然,您可以根据需要将自己的类和结构变为可变或不可变。 不可变类型(也称为值对象)在multithreading编程,函数编程中用于清除代码。
要使类或结构不可变,只需删除所有public / protected / internal setter; 并使用readonly
关键字更好地声明所有字段。
我不确定你是在寻找.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
mscorlib的一些例子:
- 所有原始类型
- 枚举
-
decimal
-
(U)IntPtr
-
DateTime
,DateTimeOffset
,TimeSpan
-
KeyValuePair<,>
– 相反,DictionaryEntry
不是不可变的 -
Tuple<...>
-
(Multicast)Delegate
– 与字符串类似,总是在更改时返回新实例。 -
Guid
-
Version
有趣的是, string
实际上并不是真正不可改变的; 但是,我们可以将它视为“几乎不可变”的类型,这意味着,不能通过公共方式(至少在安全的上下文中)更改字符串实例的内容。 但它有一个wstrcpy
内部方法, StringBuilder
类用它来操作字符串实例。