. net中不可变类型的例子

本文关键字:类型 不可变 net | 更新日期: 2023-09-27 18:05:27

我们知道不可变的概念,但除了

,我们还需要知道一些不可变类型
    字符串
  • DateTime

还有吗?

. net中不可变类型的例子

框架类库中的不可变类型列表如下:(请随意扩展!)

System.…

  • 所有原始值类型:(注意:不是所有的值类型都是不可变的!)
    • ByteSByte
    • Int16UInt16
    • Int32UInt32
    • Int64UInt64
    • IntPtr
    • Single
    • Double
  • Decimal
  • 编译器创建的所有匿名类型(c#中的new { ... }, VB.NET中的New With { ... }) (错误的原因有两个:这些类型不在FCL中,显然是VB。. NET类型是可变的)
  • 所有枚举类型(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,或现代字体家族TupleTuple是不可变的,因为它是为了支持。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/