纯函数在C#中
我知道C#正在获得大量的并行编程支持,但是AFAIK仍然没有用于副作用validation的构造,对吧?
我认为现在已经布置了C#更复杂了。 但有没有计划让这个? 或者,F#是唯一一个构build了副作用validation的.NET语言?
C#的语言不是,但.NET的框架可能是。
合同库+在.NET 4中引入的静态分析工具可能会引入这些:
微软现在正在.NET 3.5框架内使用[Immutable]和[Pure]。
例如,请参阅System.Core.dll中的.NET 3.5内的[Microsoft.Contracts.Immutable]和[Microsoft.Contracts.Pure]。 不幸的是,他们是内部的。 但是,Microsoft.Contracts。*大部分是由Spec#研究产生的,而Spec#已经被合并到将作为.NET 4.0一部分的Contracts API中。
我们将看到这是什么。 我还没有检查预发布的.NET 4.0位是否包含合同API中的[Pure]或[Immutable]之类的任何API。 如果他们这样做,我会想象静态分析工具将是执行规则,而不是编译器。
编辑我刚从本周的MS代码合同的最新预发行下载Microsoft.Contracts.dll 。 好消息:库中存在[Pure]和[Mutability(Mutability.Immutable)]属性,这表明它们将在.NET 4.0中。 呜呼!
编辑2现在.NET 4已经发布了,我查阅了这些types。 在System.Diagnostics.Contracts命名空间中, [Pure]仍然存在。 它不是为了一般用途,而是用于合同API的前后条件检查。 它不是编译器强制执行, 代码合同检查器工具也不强制执行纯度 。 [可变性]消失了。 有趣的是,当Microsoft在.NET 3.5(在System.Core.dll的内部BigInteger类)中使用Mutability和Pure属性时,.NET 4已经将BigInteger转换为System.Numerics,并且已经剥离了[Pure]和[Mutability]这种types的属性。 底线:它看起来.NET 4没有任何副作用validation。
编辑3随着最近(2011年末)预览的微软Rosyln编译器即服务工具 – 相信是计划在Visual Studio 2015 RTM – 看起来像他们将能够支持这样的东西; 你可以编写扩展到编译器检查纯度和不变性,如果用这些属性装饰的东西不遵循规则,则发出编译器警告。 即便如此,我们还是要看几年来支持这一点。
编辑4现在,Rosyln在2015年夏天已经到来了,为纯/不可变性构build编译器扩展的能力确实存在。 但是,这对于现有的框架代码和第三方库代码都没有任何帮助。 但即将到来的是C#7的不可变types的build议 。 这将由编译器强制执行,并将在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月,它似乎不可改变的types从C#7中删除。总是希望C#8. 🙂
不仅没有什么副作用validation – 甚至没有什么可以validation一个types是不可变的,这是沿着相同的路线国际海事组织小步骤。
我不相信在C#4.0中有什么东西可以下来(尽pipe我可能很容易出错)。 我真的希望不变性在C#5.0中产生影响; 当然,Eric Lippert已经在这方面做了大量的博客,而MS的人们一直在考虑并行性。
对不起,这不是一个更令人鼓舞的图片。
编辑: 犹大的答案是相当明亮的…框架的支持是否足够适合你? :)(如果代码合同的某些方面没有准备好用于.NET 4.0,我不会感到惊讶,请注意,如果可能他们保持最初的版本相对较小,稍后再提高版本。)
原则上,validation是否是不可变的,代码是否有副作用是很容易的。 类/数据结构的所有字段必须是只读的,而且它们的types必须是另一个不可变的对象。 我们还需要一种将代表标记为“纯粹”(无副作用)的方法,但这可能都是可能的。
然而,问题在于这通常太严格。 在F#中,通常会以副作用自由和不可变的风格编写代码,但在本地使用某些变化通常是有益的。 这并没有打破整体的纯粹性(从某种意义上说),并且使编写代码更容易。 但是,自动validation是困难的(意思是这是一个有趣的理论问题..)
例如,以“纯”的方式处理数组是完美的。 你可以使用像Array.map这样的方法将所有的元素都应用到一个函数中,并返回一个新的数组而不需要修改原来的数组。 该函数在返回之前对新创build的数组进行变异,但是该数组在其他地方没有变异,所以这在原理上是纯粹的 ,但很难validation(这在F#中是非常有用的编程模式)。
所以,我认为有很多事情可以做,但只是禁止所有的副作用可能不如看起来那么好。 关于合同的好处是,他们也可能在这种情况下使用。