.Net中不可变类型的示例

时间:2015-07-30 10:36:15

标签: c# .net vb.net immutability

我们知道不变性的概念,但需要知道除

之外的一些不可变类型
  • 字符串
  • 日期时间

还有更多吗?

5 个答案:

答案 0 :(得分:12)

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

System.…

  • 所有原始值类型:(注意:not all value types are immutable!)
    • ByteSByte
    • Int16UInt16
    • Int32UInt32
    • Int64UInt64
    • IntPtr
    • Single
    • Double
  • Decimal
  • 编译器创建的所有匿名类型(在C#中为new { ... },在VB.NET中为New With { ... } (错误有两个原因:这些类型不在FCL,显然VB.NET类型是可变的。)
  • 所有枚举类型(enumEnum
  • 所有代表类型。 (请参阅this answer。虽然代理可能看起来是可变的(因为您可以执行obj.PropertyChanged += callback之类的操作,但实际上obj.PropertyChanged引用已变异为指向到新构造的委托实例;原始委托实例保持不变。)
  • DateTimeTimeSpan (在this answer中提及)DateTimeOffset
  • DBNull
  • Guid
  • Nullable<T>
  • String
  • .NET 4 引入的Tuple<…>类型(在this answer中提到)
  • Uri
  • Version
  • Void

System.Linq.…

  • Lookup<TKey, TElement>

答案 1 :(得分:1)

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

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

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

    ImmutableArray(预发行版)

    ImmutableDictionary

    ImmutableSortedDictionary

    ImmutableHashSet

    ImmutableList

    ImmutableQueue

    ImmutableSortedSet

    ImmutableStack

答案 3 :(得分:0)

mscorlib

中的一些示例
  • 所有原始类型
  • 枚举
  • decimal
  • (U)IntPtr
  • DateTimeDateTimeOffsetTimeSpan
  • 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/