web-dev-qa-db-ja.com

C#には副作用の検証機能が含まれていますか(または含まれますか)?

C#が多くの並列プログラミングサポートを取得していることは知っていますが、AFAIKには副作用検証用の構成がまだありませんよね?

C#が既にレイアウトされているので、今はもっとトリッキーだと思います。しかし、これを導入する計画はありますか?または、F#は、副作用の検証のための構成体を持つ唯一の.NET言語ですか?

72
Joan Venge

C#言語はそうではありませんが、.NETフレームワークはそうかもしれません。

契約ライブラリ+ .NET 4で導入されている静的分析ツールでは、次のものが導入される可能性があります。

Microsoftは現在、.NET 3.5フレームワーク内で[Immutable]と[Pure]を使用しています。

たとえば、System.Core.dllの.NET 3.5内の[Microsoft.Contracts.Immutable]および[Microsoft.Contracts.Pure]を参照してください。残念ながら、それらは内部のものです。ただし、Microsoft.Contracts。*は主にSpec#の調査から生まれたものであり、Spec#は.NET 4.0の一部となるコントラクトAPIに組み込まれています。

これから何が起こるかを見てみましょう。プレリリースの.NET 4.0ビットに、コントラクトAPIの[Pure]や[Immutable]などのAPIが含まれているかどうかを確認していません。もしそうなら、コンパイラではなく、静的分析ツールがルールを適用するツールになると思います。

editMSコードコントラクトの最新のプレリリースドロップ からMicrosoft.Contracts.dllをロードしました。朗報:[Pure]および[Mutability(Mutability.Immutable)]属性がライブラリに存在し、.NET 4.0に含まれることを示唆しています。ウフー!

edit 2.NET 4がリリースされたので、これらのタイプを調べました。 [Pure] はまだSystem.Diagnostics.Contracts名前空間にあります。これは一般的な使用を目的としたものではなく、Contract APIの事前および事後条件チェックでの使用を目的としています。コンパイラーは強制しません コード契約チェッカーツールは純粋性を強制しません 。 【ミュータビリティ】はなくなりました。興味深いことに、Microsoftが(System.Core.dllの内部BigIntegerクラスの).NET 3.5でMutabilityおよびPure属性を使用していた場合、.NET 4はBigIntegerをSystem.Numericsに移動し、[Pure]および[Mutability]を削除しました。そのタイプの属性。 結論:.NET 4は副作用の検証には何もしません

edit 3最近(2011年後半)にプレビューされたMicrosoft Rosyln compiler-as-a-serviceツール-RTM-このようなものをサポートできるように見えます;コンパイラーに拡張機能を記述して、純粋性と不変性をチェックし、これらの属性で装飾されたものにコンパイラー警告を発行できますtルールに従ってくださいそれでも、これをサポートするために数年先を見ています。

edit 42015年夏の時点でRosylnがここにいるので、純粋/不変性のためのコンパイラー拡張を構築する機能は確かに存在します。ただし、既存のフレームワークコードやサードパーティのライブラリコードに対しては何も行いません。しかし、地平線上には 不変の型に関するC#7の提案 があります。これはコンパイラーによって強制され、新しいimmutableキーワードが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.
}

編集52016年11月で、不変の型がC#7から削除されたようです。C#8には常に希望があります:-)

編集62017年11月です。C#8が完全に表示され、純粋な関数はありませんが readonly構造体 。これにより、構造体が不変になり、いくつかのコンパイラの最適化が可能になります。

164

副作用を検証するだけでなく、型が不変であることを検証することもできません。これは、同じルートIMOに沿った小さなステップです。

C#4.0で何か問題が発生しているとは思いません(ただし、簡単に間違っている可能性があります)。私は本当に不変がC#5.0に影響を与えることを願っています。確かに、Eric Lippertはそれについてかなりブログを書いており、MSの人々は並列処理についてかなりの量を考えてきました。

申し訳ありませんが、それ以上の励みになる画像ではありません。

編集: ユダの答え はかなり明るいです...フレームワークのサポートで十分でしょうか? :)(コードコントラクトの一部の側面が.NET 4.0に対応していない場合でも、完全に驚くことはありません。おそらく、それらが最初のリリースを比較的維持していたとしても小さく、後でブーストします。)

18
Jon Skeet

原則として、何かが不変であるかどうか、およびコードに副作用がないかどうかを確認することは簡単です。クラス/データ構造のすべてのフィールドは読み取り専用でなければならず、それらのタイプは別の不変オブジェクトでなければなりません。デリゲートを "純粋"(副作用なし)としてマークする方法も必要ですが、おそらくそれはすべて可能です。

ただし、問題はこれが制限が多すぎることです。 F#では、通常、コードは副作用のない不変のスタイルで記述しますが、一部のミューテーションをローカルで使用すると効果的です。これは、全体的な純粋さを(ある意味で)壊すことはなく、コードの記述をはるかに簡単にします。ただし、これを自動的に確認することは困難です(つまり、興味深い理論上の問題であることを意味します)。

たとえば、配列を「純粋な」方法で操作することは完全に問題ありません。 Array.mapのようなメソッドをすべての要素に適用して、元の配列を変更せずにnew配列を返すことができます。 。関数はそれを返す前に(新しく作成された)配列を変更しますが、配列は他の場所では変更されないため、これは原則としてpureですが、難しい検証します(これはF#の非常に便利なプログラミングパターンです)。

だから、できることはたくさんあると思いますが、単純にすべての副作用を禁止することは、見かけほど良い方法ではないかもしれません。コントラクトのいいところは、おそらくこのシナリオでも使用できることです。

15
Tomas Petricek