C# Net中不可变类型的示例
我们知道不变性的概念,但需要知道的是除了C# Net中不可变类型的示例,c#,.net,vb.net,immutability,C#,.net,Vb.net,Immutability,我们知道不变性的概念,但需要知道的是除了 串 日期时间 还有更多吗?TimeSpan,或者现代类型的家庭元组元组是不可变的,因为它的实现支持.NET中的函数式语言(F#F.e.) 当然,您可以根据自己的意愿使自己的类和结构可变或不可变。不可变类型(也称为值对象)在多线程编程、函数编程和清除代码中非常有用 要使类或结构不可变,只需删除所有公共/受保护/内部setter;最好用readonly关键字声明所有字段。下面是框架类库中的不可变类型列表。(请随意扩展!) 系统… 所有基本值类型:(注意
- 串
- 日期时间
还有更多吗?
TimeSpan
,或者现代类型的家庭元组<代码>元组
是不可变的,因为它的实现支持.NET中的函数式语言(F#F.e.)
当然,您可以根据自己的意愿使自己的类和结构可变或不可变。不可变类型(也称为值对象)在多线程编程、函数编程和清除代码中非常有用
要使类或结构不可变,只需删除所有公共/受保护/内部setter;最好用
readonly
关键字声明所有字段。下面是框架类库中的不可变类型列表。(请随意扩展!)
系统…
- 所有基本值类型:(注意:!)
和Byte
SByte
和Int16
UInt16
和Int32
UInt32
和Int64
UInt64
IntPtr
Single
Double
Decimal
- 编译器创建的所有匿名类型(
在C#中,new{…}
在VB.NET中)(错误原因有两个:这些类型不在FCL中,显然VB.NET类型是可变的。)new With{…}
- 所有枚举类型(
,enum
)enum
- 所有委托类型。(请参阅。虽然委托似乎是可变的(因为您可以执行
,但实际上是obj.PropertyChanged+=callback
引用发生了变化,指向新构造的委托实例;原始委托实例保持不变。)obj.PropertyChanged
,DateTime
(在中提到)和TimeSpan
DateTimeOffset
DBNull
Guid
Nullable
String
- .NET4引入的
类型(在中提到)Tuple
Uri
版本
Void
System.Linq….
查找
public readonly int[] Numbers;
使其不可更改?数字本身不能更改,但其内容可以更改。你明白了
无论如何,您可以通过编程方式检查自己。对于更深层次的嵌套检查,您将需要递归(我在这里不会这样做)
加载所有要检查的程序集,并执行类似操作(未测试)
即使这样,也不足以找到集合类型的不可变性。一些不可变集合类型(虽然不是默认.NET core的一部分)可以在此处找到:
一些值得注意的不可变因素:
- 一些类类型,如
,String
,匿名类型Tuple
- 大多数结构(值得注意的例外包括大多数枚举数)
- 列举
- 代表
- 不可变的集合类型,如 ImmutableArray(预发布版本) 不可变字典 不可变排序字典 不可变哈希集 不可变列表 不可变队列 不可变排序集 不可变粘性
- 所有的基本类型
- 列举
decimal
(U)IntPtr
,DateTime
,DateTimeOffset
TimeSpan
-相反,KeyValuePair
不是不可变的DictionaryEntry
Tuple
-与字符串类似,在更改新实例时始终返回新实例(多播)委托
Guid
版本
- 来自mscorlib的一些示例:
string
实际上并不是不可变的;但是,我们可以将其视为“实际上不可变”类型,这意味着string实例的内容不能通过公共方式更改(至少在安全上下文中)但是它有一个wstrcpy
内部方法,它被StringBuilder
类用来操作字符串实例。使用.NET 5和新的C#9.0版本,现在几乎每个对象都可以是不可变的(或者在属性中包含不可变的状态)
这里有更多信息:大多数人只知道字符串,更不用说DateTime了。因此,我提出了一个问题来帮助我们的开发者社区。Re:创建一个不可变类型列表以便于参考。这是个好主意,但也许最好只有一个(社区wiki)答案是每个人都可以扩展;否则,我们最终会得到大量答案,其中大多数答案可能只列出框架中不可变类型的一小部分。要清楚的是,仅仅因为值类型碰巧是不可变的,并不意味着所有不可变对象都是值类型……一种在不改变其内部状态的类型从外部进行OSBerable操作可能是不可变的:例如,一个昂贵的属性延迟计算一次,然后缓存结果。不可变的类型不一定意味着
只读
字段。@Claies,是的,当然。我的文本中的值对象是一个模式名,而不是.NET值类型。这个模式由f.e.@InBetween,y描述你是对的。然而,这种可能性表明这个类至少有两种责任。这违反了OO设计。因此,你可以这样做,但你不应该这样做。@MarkShevchenko:)我写了评论后,开始对它进行更多思考,最后我问了很多,因为我不确定正确的answ是什么
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();