C#是否(或将)包括副作用验证功能?

C#是否(或将)包括副作用验证功能?,c#,.net,f#,parallel-processing,immutability,C#,.net,F#,Parallel Processing,Immutability,我知道C#得到了很多并行编程的支持,但似乎还没有用于副作用验证的结构,对吗 我想现在C#已经布置好了,这就更棘手了。但是有没有计划把这个放进去?或者F#是唯一一种具有用于副作用验证的结构的.NET语言吗?不仅没有用于副作用验证的东西——甚至没有什么东西可以验证类型是不可变的,这是沿着相同路线迈出的一小步 我不相信在C#4.0中会有任何事情发生(尽管我很容易出错)。我真的希望不变性能对C#5.0产生影响;当然,Eric Lippert已经在博客上写了很多关于并行性的文章,微软的同事们也在考虑相当多

我知道C#得到了很多并行编程的支持,但似乎还没有用于副作用验证的结构,对吗


我想现在C#已经布置好了,这就更棘手了。但是有没有计划把这个放进去?或者F#是唯一一种具有用于副作用验证的结构的.NET语言吗?

不仅没有用于副作用验证的东西——甚至没有什么东西可以验证类型是不可变的,这是沿着相同路线迈出的一小步

我不相信在C#4.0中会有任何事情发生(尽管我很容易出错)。我真的希望不变性能对C#5.0产生影响;当然,Eric Lippert已经在博客上写了很多关于并行性的文章,微软的同事们也在考虑相当多的并行性问题

对不起,这不是一张更令人鼓舞的照片

编辑:是相当光明的。。。框架支持对您来说足够好吗?:)(请注意,如果代码契约的某些方面没有为.NET 4.0做好准备,我不会完全感到惊讶——如果他们可能会保持初始版本相对较小,并在以后对其进行升级的话。)

C#该语言不是,但.NET框架可能是

在.NET 4中引入的契约库+静态分析工具可能会引入以下内容:

微软目前正在.NET3.5框架内使用[Immutable]和[Pure]

例如,请参见.NET 3.5中System.Core.dll中的[Microsoft.Contracts.Immutable]和[Microsoft.Contracts.Pure]。不幸的是,它们是内部的。然而,Microsoft.Contracts.*主要是从规范研究中诞生的,规范已经被合并到将成为.NET 4.0一部分的Contracts API中

我们来看看结果如何。我还没有检查预发布的.NET 4.0位是否在Contracts API中包含任何类似于[Pure]或[Immutable]的API。如果他们这样做,我想静态分析工具将是执行规则的工具,而不是编译器

编辑我刚从本周开始加载了Microsoft.Contracts.dll。好消息:[Pure]和[Mutability(Mutability.Immutable)]属性存在于库中,这表明它们将出现在.NET4.0中。呜呼

编辑2现在.NET 4已经发布,我查找了这些类型。仍存在于System.Diagnostics.Contracts命名空间中。它不是用于一般用途,而是用于合同API的前后条件检查。它不是编译器强制执行的。[易变性]消失了。有趣的是,当微软在.NET3.5中使用易变性和纯属性时(在System.Core.dll的内部BigInteger类中),.NET4将BigInteger移动到System.Numerics中,并将[Pure]和[Mutability]属性从该类型中剥离底线:看来.NET 4对副作用验证没有任何作用。

编辑3最近(2011年底)预览的Microsoft Rosyln compiler-as-a-service工具(据信将在Visual Studio 2015中用于RTM)看起来可以支持这样的东西;您可以向编译器编写扩展来检查纯度和不变性,并在使用这些属性修饰的内容不符合规则时发出编译器警告。即便如此,我们仍在考虑几年后支持这一点

编辑4既然Rosyln在2015年夏天就在这里,那么为纯/不变性构建编译器扩展的能力确实存在。但是,这对现有框架代码和第三方库代码都没有任何作用。但即将到来的是一场灾难。这将由编译器强制执行,并将向C#引入一个新的不可变的关键字和.NET framework中的[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将支持,这是完全不可变的类型。此外,记录将具有用于从现有记录创建新记录以表示新状态的表达式。

原则上,验证某些内容是否不可变以及代码是否缺少副作用很容易。类/数据结构的所有字段都必须是只读的,并且它们的类型必须是另一个不可变对象。我们还需要一种将代理标记为“纯”(无副作用)的方法,但这可能都是可能的

然而,问题是,这往往过于严格。在F#中,您通常会以无副作用且不可变的方式编写代码,但在局部使用一些变异通常是有益的。这并没有破坏整体的纯洁性(在某种意义上),并使编写代码变得更加容易。然而,自动验证这一点是困难的(意味着这是一个有趣的理论问题……)

例如,以“纯”的方式使用数组是完全可以的。您可以使用类似于Array.map的方法,将某些函数应用于所有元素,并返回一个新数组,而无需修改原始数组。函数会在返回(新创建的)数组之前对其进行变异,但数组不会在其他任何地方进行变异,因此这在原则上是纯粹的,但很难验证(这是F#中非常有用的编程模式)


所以,我认为有很多事情可以做,但简单地禁止所有副作用可能并不像看上去那样好。合同的好处在于,它们可能也可以用于这种情况。

谢谢Jon。欢迎您的见解:)我只是想看看该部门的情况。欢迎您就这个答案是否仍然有用或是否正确发表意见