Tag: immutability

在C#中只读二维数组

在C#中是否有任何已建立的返回只读二维数组的方法? 我知道ReadOnlyCollection是用于1-d数组的正确选择,我很乐意编写自己的包装类来实现this[] {get} 。 但是如果这个轮子已经存在,我不想重新发明轮子。

不可变类与不可变结构

我有一个开始生活变得可变的课程,但我已经让它变得一成不变。 我应该把它改成struct吗? 选择一个而不是另一个需要考虑哪些因素? 我的特殊情况是Point类型(它表示自定义坐标系中的坐标),它由4个int字段组成,还有一些属性以不同的方式访问相同的数据。 我注意到String是一个类并且是不可变的,因此必须有一些用例。

在C#中使用F#数据类型

更具体地说,我真的想要一个不可变/共享的链表,我认为拥有不可变的地图和集合也会很好。 只要我不必担心核心实现,我就可以轻松添加扩展方法/子类/包装它,为我自己提供一个合理的外部接口。 我有什么理由不这样做吗? 性能,不兼容性等?

检测不可变量的高效方法?

我有一个实用程序,旨在传递我们系统周围的对象。 由于它是一个multithreading环境,因此该实用程序会对其传递的每个对象进行深层复制,以防止出现任何线程安全问题。 我正在努力转换我们的系统以使用不可变对象来消除对此副本的需要。 我想知道检测对象是不可变的最好(最快)方法是什么? 我的第一个想法就是了解我们放在所有不可变对象(MessageAttribute)上的属性。 正如您从下面的性能配置文件中看到的那样,它会受到很大影响(大约是所有其他检查执行时间的10倍)。 我怎么能检测到我的不可变通过? 我可以做一个typeof()比较,看起来效果更好,但这看起来相当笨拙,而且随着我们一直添加更多不可变的东西,它将是难以维护的。 编辑:我忘了提到布尔值被重构为变量以用于分析,实际上,结果存储在isDefined的表达式实际上是在else if语句中,因此将被击中大约10倍。这个配置文件(我更关心平均执行时间而不是绝对执行时间)。

ReadOnlyCollection vs Liskov – 如何正确建模可变集合的不可变表示

Liskov替换原则要求子类型必须满足超类型的契约。 根据我的理解,这将导致ReadOnlyCollection违反Liskov。 ICollection的合同公开了Add和Remove操作,但只读子类型不满足此合约。 例如, IList collection = new List(); collection = new System.Collections.ObjectModel.ReadOnlyCollection(collection); collection.Add(new object()); — not supported exception 显然需要不可变的集合。 有没有关于.NET的建模方法的事情? 有什么比这更好的方法呢? IEnumerable很好地暴露了一个集合,至少看起来是不可变的。 但是,语义是非常不同的,主要是因为IEnumerable没有明确地暴露任何状态。 在我的特定情况下,我正在尝试构建一个不可变的DAG类来支持FSM 。 我显然在开始时需要AddNode / AddEdge方法,但我不希望它一旦运行就可以更改状态机。 我很难表示DAG的不可变和可变表示之间的相似性。 现在,我的设计涉及预先使用DAG Builder,然后创建一次不可变图,此时它不再可编辑。 Builder和具体的不可变DAG之间唯一的通用接口是Accept(IVisitor visitor) 。 我担心,面对可能更简单的选择,这可能是过度设计/过于抽象。 与此同时,我无法接受我可以在我的图形界面上公开可能在客户端获得特定实现时抛出NotSupportedException的方法。 处理这个问题的正确方法是什么?

ImmutableList 中的性能降低Microsoft.Bcl.Immutable中的删除方法

从NuGet包Microsoft.Bcl.Immutable版本1.0.34以及1.1.22-beta中体验Microsoft ImmutableList一些意外性能 从不可变列表中删除项目时,性能非常慢。 对于包含20000个整数值(1 … 20000)的ImmutableList ,如果开始从值20000移除到1,则从列表中删除所有项目大约需要52秒。 如果我使用通用List执行相同操作,我在每次删除操作后创建列表副本大约需要500毫秒。 我对这些结果感到有些惊讶,因为我认为ImmutableList比复制通用List更快,但也许这是预期的? 示例代码 // Generic List Test var genericList = new List(); var sw = Stopwatch.StartNew(); for (int i = 0; i < 20000; i++) { genericList.Add(i); genericList = new List(genericList); } sw.Stop(); Console.WriteLine(“Add duration for List: ” + sw.ElapsedMilliseconds); IList completeList = new List(genericList); sw.Restart(); // Remove […]

如何确定一个类在C#中是不可变的?

如何确定一个类在C#中是不可变的?

在深度不可变类型上进行延迟初始化是否需要锁定?

如果我有一个非常不可变的类型(所有成员都是只读的,如果它们是引用类型成员,那么它们也引用了非常不可变的对象)。 我想在类型上实现一个惰性初始化属性,如下所示: private ReadOnlyCollection m_PropName = null; public ReadOnlyCollection PropName { get { if(null == m_PropName) { ReadOnlyCollection temp = /* do lazy init */; m_PropName = temp; } return m_PropName; } } 据我所知: m_PropName = temp; ……是线程安全的。 我并不担心两个线程同时竞争初始化,因为它很少见,从逻辑角度来看两个结果都是相同的,如果我没有,我宁愿不使用锁至。 这会有用吗? 优缺点都有什么? 编辑:谢谢你的回答。 我可能会继续使用锁。 但是,我很惊讶没有人提出编译器意识到临时变量是不必要的可能性,只是直接分配给m_PropName。 如果是这种情况,则读取线程可能会读取尚未完成构造的对象。 编译器是否会阻止这种情况? (答案似乎表明运行时不会允许这种情况发生。) 编辑:所以我决定使用由Joe Duffy撰写的这篇文章启发的Interlocked CompareExchange方法。 基本上: private ReadOnlyCollection m_PropName = […]

我们可以从c#访问F#复制和更新function吗?

例如在F#中我们可以定义 type MyRecord = { X: int; Y: int; Z: int } let myRecord1 = { X = 1; Y = 2; Z = 3; } 并且我可以做更新 let myRecord2 = { myRecord1 with Y = 100; Z = 2 } 这很棒,而且记录自动实现IStructuralEquality而不需要额外的努力这一事实让我希望在C#中实现这一点。 但是,也许我可以在F#中定义我的记录,但仍然可以在C#中执行一些更新。 我想像一个API MyRecord myRecord2 = myRecord .CopyAndUpdate(p=>pY, 10) .CopyAndUpdate(p=>pZ, 2) 有没有办法,我不介意脏黑客,如上所述实施CopyAndUpdate? CopyAndUpdate的C#签名将是 T CopyAndUpdate […]

在C#中,不可变和只读是什么意思?

是否正确无法更改不可变对象的值? 我有两个关于readonly场景,我想了解: 如果我有一个集合并将其标记为readonly ,如下所示。 我还可以打电话给_items.Add吗? private readonly ICollection _items; 并且对于以下变量,如果稍后我调用_metadata.Change ,它将更改Metadata实例中的一对成员变量的内部值。 _metadata仍然是不可变的吗? private readonly Metadata _metadata; 对于上面的两个变量,我完全理解我不能在初始化器和构造器之外直接为它们分配新值。