我知道C#得到了很多并行编程支持,但是AFAIK仍然没有用于副作用验证的结构,对吗?
我认为现在已经布局C#更加棘手。但是有计划将其纳入其中吗?还是F#是唯一具有副作用验证构造的.NET语言?
我知道C#得到了很多并行编程支持,但是AFAIK仍然没有用于副作用验证的结构,对吗?
我认为现在已经布局C#更加棘手。但是有计划将其纳入其中吗?还是F#是唯一具有副作用验证构造的.NET语言?
Answers:
C#语言不是,但是.NET框架可能是。
.NET 4中引入的Contracts库+静态分析工具可能会引入以下内容:
Microsoft现在在.NET 3.5框架中使用[Immutable]和[Pure]。
例如,请参阅System.Core.dll中的.NET 3.5中的[Microsoft.Contracts.Immutable]和[Microsoft.Contracts.Pure]。不幸的是,它们是内部的。但是,Microsoft.Contracts。*主要是由Spec#研究产生的,并且Spec#已被折叠到Contracts API中,该API将是.NET 4.0的一部分。
我们将看到结果。我没有检查过预发布的.NET 4.0位是否包含Contracts API中的任何API,例如[Pure]或[Immutable]。如果可以,我想静态分析工具将是执行规则的工具,而不是编译器。
编辑我刚刚从本周最新的MS Code Contract预发行版本中加载了Microsoft.Contracts.dll 。好消息:库中存在[Pure]和[Mutability(Mutability.Immutable)]属性,这表明它们将位于.NET 4.0中。hoo!
编辑2现在.NET 4已发布,我查找了这些类型。[Pure]仍然存在于System.Diagnostics.Contracts命名空间中。它不是供一般使用的,而是与Contract API的前后条件检查一起使用的。它不是编译器强制执行的,代码合同检查器工具也不是强制执行pure的。[可变性]不见了。有趣的是,Microsoft在.NET 3.5(在System.Core.dll的内部BigInteger类中)中使用Mutability和Pure属性的地方,.NET 4已将BigInteger移入System.Numerics,并剥离了[Pure]和[Mutability]该类型的属性。底线:.NET 4对于副作用验证没有任何作用。
edit 3借助最近(2011年末)预览的Microsoft Rosyln编译即服务工具-据信该工具计划在Visual Studio 2015中用于RTM-看起来它们将能够支持此类工具;您可以向编译器编写扩展,以检查其纯度和不变性,如果用这些属性修饰的内容不遵循规则,则发出编译器警告。即使如此,我们仍在寻找几年来支持这一点。
编辑4既然Rosyln截止到2015年夏天就已经存在,那么确实存在为纯净/不变性构建编译器扩展的能力。但是,这对于现有框架代码或第三方库代码都无济于事。但即将出现的是针对不变类型的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.
}
编辑5这是2016年11月,并且似乎从C#7中删除了不可变的类型。对于C#8总是有希望的。:-)
编辑6现在是2017年11月。C#8进入了全面的视野,尽管我们没有纯函数,但我们将拥有只读结构。这使结构不可变,从而允许进行多个编译器优化。
编辑7现在是2020年7月,C#9即将支持完全不变的记录类型。此外,记录将具有With表达式,用于从现有记录创建新记录以表示新状态。
不仅没有什么可以进行副作用验证的,甚至没有任何方法可以验证类型是不可变的,这是沿着IMO相同路线的一个小步骤。
我不相信在C#4.0中会有什么事情发生(尽管我很容易错了)。我真的希望不变性能对C#5.0产生影响。当然,埃里克·利珀特(Eric Lippert)在博客上写了很多,而MS的人们一直在考虑并行性。
抱歉,这不是更令人鼓舞的情况。
编辑:犹大的答案要聪明得多...框架支持对您来说足够好吗?:)(请注意,如果代码契约的某些方面还没有为.NET 4.0做好准备,我不会感到完全惊讶,如果它们使初始版本相对较小并在以后进行了增强。)
原则上,验证某些东西是否是不变的以及代码是否没有副作用是容易的。类/数据结构的所有字段必须是只读的,并且它们的类型必须是另一个不可变的对象。我们还需要一种将代表标记为“纯”(无副作用)的方法,但这可能是可能的。
但是,问题在于这通常过于严格。在F#中,您通常会以无副作用且不可变的副作用编写代码,但是在本地使用某些变更通常会有所帮助。从某种意义上讲,这不会破坏整体纯度,并且使编写代码变得更加容易。但是,自动验证非常困难(意味着这是一个有趣的理论问题。)
例如,以“纯”方式使用数组是完全可以的。您可以使用诸如Array.map之类的方法,这些方法将某些函数应用于所有元素,并返回一个新数组,而无需修改原始数组。该函数在返回之前先对(新创建的)数组进行了变异,但是该数组在其他任何地方都没有变异,因此,这在原则上是纯净的,但很难验证(这在F#中是非常有用的编程模式)。
因此,我认为可以做很多事情,但是简单地禁止所有副作用可能并不像看起来那样好。合同的好处是,它们也可能在这种情况下使用。