C# 是否(或将要)包括副作用验证功能?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/592934/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Does (or will) C# include features for side-effects verification?
提问by Joan Venge
I know C# is getting a lot of parallel programming support, but AFAIK there is still no constructs for side-effects verification, right?
我知道 C# 获得了很多并行编程支持,但 AFAIK 仍然没有用于副作用验证的构造,对吗?
I assume it's more tricky now that C# is already laid out. But are there plans to get this in? Or is F# the only .NET language that has constructs for side-effects verification?
我认为现在 C# 已经布局更棘手。但是有计划加入吗?或者 F# 是唯一具有副作用验证构造的 .NET 语言吗?
采纳答案by Judah Gabriel Himango
C# the language isn't, but .NET the framework may be.
C# 语言不是,但 .NET 框架可能是。
The Contracts library + the static analysis tools being introduced in .NET 4 might introduce these:
.NET 4 中引入的 Contracts 库 + 静态分析工具可能会引入这些:
Microsoft is using [Immutable] and [Pure] inside .NET 3.5 framework right now.
Microsoft 目前正在 .NET 3.5 框架中使用 [Immutable] 和 [Pure]。
For example, see [Microsoft.Contracts.Immutable] and [Microsoft.Contracts.Pure] inside .NET 3.5, in the System.Core.dll. Unfortunately, they're internal. However, Microsoft.Contracts.* is mostly born out of Spec# research, and Spec# has been folded into the Contracts APIs that will be part of .NET 4.0.
例如,请参阅 System.Core.dll 中 .NET 3.5 中的 [Microsoft.Contracts.Immutable] 和 [Microsoft.Contracts.Pure]。不幸的是,它们是内部的。但是,Microsoft.Contracts.* 主要是从 Spec# 研究中诞生的,并且 Spec# 已被合并到将成为 .NET 4.0 一部分的 Contracts API 中。
We'll see what comes of this. I haven't checked to see if the pre-release .NET 4.0 bits contain any APIs like [Pure] or [Immutable] in the Contracts APIs. If they do, I'd imagine the static analysis tool will be the one to enforce the rule, rather than the compiler.
我们会看看结果如何。我还没有检查预发布的 .NET 4.0 位是否在 Contracts API 中包含任何 API,如 [Pure] 或 [Immutable]。如果他们这样做,我想静态分析工具将是强制执行规则的工具,而不是编译器。
editI just loaded up Microsoft.Contracts.dll from the latest pre-release drop of MS Code Contractsthis week. Good news: [Pure] and [Mutability(Mutability.Immutable)] attributes exist in the library, which suggests they will be in .NET 4.0. Woohoo!
编辑我刚刚从本周最新的预发布版 MS Code Contracts 中加载了 Microsoft.Contracts.dll 。好消息:[Pure] 和 [Mutability(Mutability.Immutable)] 属性存在于库中,这表明它们将出现在 .NET 4.0 中。呜呼!
edit 2Now that .NET 4 has been released, I looked up these types. [Pure]is still there in System.Diagnostics.Contracts namespace. It's not intended for general use, but rather, for use with the Contract API's pre- and post-condition checking. It is not compiler enforced, neither does the Code Contract checker tool enforce purity. [Mutability] is gone. Interestingly, where Microsoft was using Mutability and Pure attributes in .NET 3.5 (in the internal BigInteger class in System.Core.dll), .NET 4 has moved BigInteger into System.Numerics, and has stripped the [Pure] and [Mutability] attributes off that type. Bottom line: it appears .NET 4 does nothing for side-effects verification.
编辑 2现在 .NET 4 已经发布,我查找了这些类型。[Pure]仍然存在于 System.Diagnostics.Contracts 命名空间中。它不是用于一般用途,而是用于合同 API 的前置和后置条件检查。它不是编译器强制执行的,代码契约检查器工具也不强制纯度。[可变性] 消失了。有趣的是,微软在 .NET 3.5 中使用 Mutability 和 Pure 属性(在 System.Core.dll 的内部 BigInteger 类中),.NET 4 已经将 BigInteger 移到 System.Numerics 中,并剥离了 [Pure] 和 [Mutability]该类型的属性。底线:似乎 .NET 4 对副作用验证没有任何作用。
edit 3With the recently (late 2011) previewed Microsoft Rosyln compiler-as-a-service tools -- believed to be scheduled for RTM in Visual Studio 2015 -- look like they'll be able to support stuff like this; you could write extensions to the compiler to check for purity and immutability, and issue compiler warnings if something decorated with those attributes don't follow the rules. Even so, we're looking at a few years out to support this.
编辑 3使用最近(2011 年末)预览的 Microsoft Rosyln 编译器即服务工具——据信计划用于 Visual Studio 2015 中的 RTM——看起来他们将能够支持这样的东西;您可以为编译器编写扩展以检查纯度和不变性,并在使用这些属性修饰的内容不符合规则时发出编译器警告。即便如此,我们正在考虑用几年时间来支持这一点。
edit 4Now that Rosyln is here as of summer 2015, the ability to build a compiler extension for pure/immutability does indeed exist. However, that doesn't do anything for existing framework code, nor 3rd party library code. But on the horizon is a C# 7 proposal for immutable types. This would be enforced by the compiler and would introduce a new immutablekeyword to C# and a [Immutable] attribute in the .NET framework. Usage:
编辑 4既然 Rosyln 已于 2015 年夏季发布,那么确实存在为纯/不变性构建编译器扩展的能力。但是,这对现有框架代码和 3rd 方库代码没有任何作用。但是即将出现的是针对不可变类型的C# 7 提案。这将由编译器强制执行,并将在 C# 中引入一个新的不可变关键字,并在 .NET 框架中引入一个 [Immutable] 属性。用法:
// Edit #4: This is a proposed design for C# 7 immutable as of June 2015.
// Compiler will implicitly mark all fields as readonly.
// Compiler will enforce all fields must be immutable types.
public immutable class Person
{
public Person(string firstName, string lastName, DateTimeOffset birthDay)
{
FirstName = firstName; // Properties can be assigned only in the constructor.
LastName = lastName;
BirthDay = birthDay;
}
public string FirstName { get; } // String is [Immutable], so OK to have as a readonly property
public string LastName { get; }
public DateTime BirthDay { get; } // Date is [Immutable] too.
}
edit 5It's November 2016, and it appears immutable types were dropped from C# 7. There's always hope for C# 8. :-)
编辑 5现在是 2016 年 11 月,似乎不可变类型已从 C# 7 中删除。C# 8 总是有希望的。:-)
edit 6It's November 2017. C# 8 is coming into full view, and while we won't have pure functions, we will have readonly structs. This makes a struct immutable, which allows several compiler optimizations.
编辑 6现在是 2017 年 11 月。C# 8 即将全面发布,虽然我们不会有纯函数,但我们会有只读 structs。这使得结构体不可变,从而允许多个编译器优化。
回答by Jon Skeet
Not only is there nothing for side-effect verification - there's nothing even to verify that a type is immutable, which is a smaller step along the same route IMO.
不仅没有任何副作用验证 - 甚至没有任何东西可以验证类型是不可变的,这是沿着 IMO 相同路线的一小步。
I don't believe there's anything coming down the pipe in C# 4.0 (although I could easily be wrong). I really hopethat immutability makes an impact in C# 5.0; certainly Eric Lippert has blogged quite a bit about it, and folks at MS have been thinking about parallelism a fair amount.
我不相信在 C# 4.0 中会有任何进展(尽管我很容易出错)。我真的希望不变性对 C# 5.0 产生影响;当然,Eric Lippert 已经写了很多关于它的博客,MS 的人们一直在考虑并行性。
Sorry it's not a more encouraging picture.
抱歉,这不是更令人鼓舞的画面。
Edit: Judah's answeris considerably brighter... would framework support be good enough for you? :) (I wouldn't be entirely surprised if some aspects of Code Contracts weren't ready for .NET 4.0, mind you - if perhaps they kept the initial release relativelysmall and boosted it later.)
编辑:犹大的答案要好得多......框架支持对你来说是否足够好?:)(如果 Code Contracts 的某些方面还没有为 .NET 4.0 做好准备,我不会感到完全惊讶,请注意 - 如果他们保持初始版本相对较小并稍后对其进行提升。)
回答by Tomas Petricek
In principle, verifying whether something is immutable & whether the code lacks side-effects is easy. All fields of the class/data structure must be readonly and their type must be another immutable object. We'd also need a way for marking a delegate as "pure" (side-effect free), but that would probably all be possible.
原则上,验证某些东西是否不可变以及代码是否缺少副作用很容易。类/数据结构的所有字段都必须是只读的,并且它们的类型必须是另一个不可变对象。我们还需要一种将委托标记为“纯”(无副作用)的方法,但这可能都是可能的。
However, the problem is that this is often too restrictive. In F#, you'd generally write the code in a side-effect free & immutable style, but it is often beneficial to use some mutation locally. This doesn't break the overall purity (in some sense) and makes it much easier to write the code. However, verifying this automatically is difficult (meanin that it's an interesting theoretical problem..)
然而,问题是这通常过于严格。在 F# 中,您通常会以无副作用且不可变的风格编写代码,但在本地使用一些更改通常是有益的。这不会破坏整体的纯度(在某种意义上),并且使编写代码变得更加容易。但是,自动验证这一点很困难(意味着这是一个有趣的理论问题..)
For example, it's perfectly fine to work with arrays in a "pure" way. You can have methods like Array.mapthat apply some function to all elements and return a newarray without modifying the original one. The function mutates the (newly created) array before returning it, but the array isn't mutated anywhere else, so this is in principle pure, but hard to verify (and this is quite useful programming pattern in F#).
例如,以“纯粹”的方式处理数组是完全没问题的。您可以使用Array.map 之类的方法,将某个函数应用于所有元素并返回一个新数组,而无需修改原始数组。该函数在返回(新创建的)数组之前对其进行变异,但该数组不会在其他任何地方发生变异,因此原则上是pure,但很难验证(这是 F# 中非常有用的编程模式)。
So, I think there is a lot that could be done, but simply banning all side-effects may not be as good way as it appears to be. The nice thing about contracts is that they could be probably used in this scenario as well.
所以,我认为有很多事情可以做,但简单地禁止所有副作用可能不像看起来那么好。合约的好处是它们也可以用于这种场景。