.Net中不可变类型的示例

我们知道不变性的概念,但除了需要知道几个不可变类型

  • 约会时间

还有更多吗?

下面是框架类库中的不可变类型列表。 (随意扩展它!)

System.…

  • 所有原始值类型:( 注意: 并非所有值类型都是不可变的 !)
    • ByteSByte
    • Int16UInt16
    • Int32UInt32
    • Int64UInt64
    • IntPtr
    • Single
    • Double
  • Decimal
  • 编译器创建的所有匿名类型(C#中的New With { ... } ,VB.NET中的New With { ... } (错误有两个原因:这些类型不在FCL中,显然VB.NET类型是可变的。)
  • 所有枚举类型( enumEnum
  • 所有代表类型。 (看到这个答案 。虽然看起来委托是可变的(因为你可以做像obj.PropertyChanged += callback这样的事情,它实际上是obj.PropertyChanged引用,它被变异指向一个新构造的委托实例;原始委托实例保持不变。)
  • DateTimeTimeSpan (在本回答中提到)DateTimeOffset
  • DBNull
  • Guid
  • Nullable
  • String
  • .NET 4引入的Tuple<…>类型(在本回答中提到)
  • Uri
  • Version
  • Void

System.Linq.…

  • Lookup

TimeSpan ,或现代型家庭TupleTuple是不可变的,因为它实现了支持.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


一些值得注意的不可变因素:

  • 一些类类型,如StringTuple ,匿名类型
  • 大多数结构(值得注意的例外包括大多数调查员)
  • 枚举
  • 代表
  • 不可变的集合类型

    ImmutableArray(预发行版)

    ImmutableDictionary

    ImmutableSortedDictionary

    ImmutableHashSet

    ImmutableList

    ImmutableQueue

    ImmutableSortedSet

    ImmutableStack

mscorlib的一些例子:

  • 所有原始类型
  • 枚举
  • decimal
  • (U)IntPtr
  • DateTimeDateTimeOffsetTimeSpan
  • KeyValuePair<,> – 相反, DictionaryEntry不是不可变的
  • Tuple<...>
  • (Multicast)Delegate – 与字符串类似,总是在更改时返回新实例。
  • Guid
  • Version

有趣的是, string实际上并不是真正不可改变的; 但是,我们可以将它视为“几乎不可变”的类型,这意味着,不能通过公共方式(至少在安全的上下文中)更改字符串实例的内容。 但它有一个wstrcpy内部方法, StringBuilder类用它来操作字符串实例。