Enthält (oder wird) C # Funktionen zur Überprüfung von Nebenwirkungen? [geschlossen]

70

Ich weiß, dass C # viel Unterstützung für die parallele Programmierung erhält, aber AFAIK, es gibt immer noch keine Konstrukte für die Überprüfung von Nebenwirkungen, oder?

Ich nehme an, es ist jetzt schwieriger, da C # bereits angelegt ist. Aber gibt es Pläne, dies zu erreichen? Oder ist F # die einzige .NET-Sprache, die Konstrukte zur Überprüfung von Nebenwirkungen enthält?

Joan Venge
quelle

Antworten:

170

C # die Sprache ist nicht, aber .NET das Framework kann sein.

Die Vertragsbibliothek + die in .NET 4 eingeführten statischen Analysetools können Folgendes einführen:

Microsoft verwendet derzeit [Unveränderlich] und [Rein] in .NET 3.5 Framework.

Siehe beispielsweise [Microsoft.Contracts.Immutable] und [Microsoft.Contracts.Pure] in .NET 3.5 in der System.Core.dll. Leider sind sie intern. Microsoft.Contracts. * Entsteht jedoch hauptsächlich aus der Forschung zu Spec #, und Spec # wurde in die Vertrags-APIs integriert, die Teil von .NET 4.0 sein werden.

Wir werden sehen, was daraus wird. Ich habe nicht überprüft, ob die .NET 4.0-Bits vor der Veröffentlichung APIs wie [Pure] oder [Immutable] in den Vertrags-APIs enthalten. In diesem Fall würde ich mir vorstellen, dass das statische Analysetool die Regel erzwingt und nicht der Compiler.

Bearbeiten Ich habe gerade Microsoft.Contracts.dll aus dem letzten Pre-Release-Drop von MS Code Contracts diese Woche geladen . Gute Nachrichten: Die Attribute [Pure] und [Mutability (Mutability.Immutable)] sind in der Bibliothek vorhanden, was darauf hindeutet, dass sie in .NET 4.0 enthalten sein werden. Woohoo!

edit 2 Nachdem .NET 4 veröffentlicht wurde, habe ich diese Typen nachgeschlagen. [Pure] ist noch im System.Diagnostics.Contracts-Namespace vorhanden. Es ist nicht für den allgemeinen Gebrauch gedacht, sondern für die Verwendung mit der Überprüfung der Vertrags-API vor und nach dem Zustand. Es wird weder vom Compiler erzwungen, noch wird das Code Contract Checker-Tool die Reinheit erzwingen . [Veränderlichkeit] ist weg. Interessanterweise hat .NET 4 BigInteger in System.Numerics verschoben und die Attribute [Pure] und [Mutability] entfernt, wenn Microsoft in .NET 3.5 (in der internen BigInteger-Klasse in System.Core.dll) die Attribute Mutability und Pure verwendet hat. Attribute von diesem Typ. Fazit: Es scheint, dass .NET 4 nichts für die Überprüfung von Nebenwirkungen tut.

edit 3 Mit den kürzlich (Ende 2011) vorgestellten Microsoft Rosyln-Compiler-as-a-Service-Tools, von denen angenommen wird, dass sie für RTM in Visual Studio 2015 geplant sind, sehen sie so aus, als könnten sie solche Dinge unterstützen. Sie können Erweiterungen in den Compiler schreiben, um die Reinheit und Unveränderlichkeit zu überprüfen, und Compiler-Warnungen ausgeben, wenn etwas, das mit diesen Attributen dekoriert ist, nicht den Regeln entspricht. Trotzdem schauen wir uns ein paar Jahre Zeit, um dies zu unterstützen.

edit 4 Jetzt, da Rosyln ab Sommer 2015 hier ist, besteht tatsächlich die Möglichkeit, eine Compiler-Erweiterung für Reinheit / Unveränderlichkeit zu erstellen. Dies hat jedoch nichts mit vorhandenem Framework-Code oder Bibliothekscode von Drittanbietern zu tun. Am Horizont steht jedoch ein C # 7-Vorschlag für unveränderliche Typen . Dies würde vom Compiler erzwungen und ein neues unveränderliches Schlüsselwort für C # und ein [unveränderliches] Attribut im .NET Framework einführen . Verwendung:

// 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 5 Es ist November 2016 und es scheint, dass unveränderliche Typen von C # 7 gestrichen wurden. Es gibt immer Hoffnung für C # 8 .:-)

edit 6 Es ist November 2017. C # 8 wird vollständig angezeigt , und obwohl wir keine reinen Funktionen haben, werden wir schreibgeschützte Strukturen haben . Dies macht eine Struktur unveränderlich, was mehrere Compileroptimierungen ermöglicht.

edit 7 Es ist Juli 2020 und C # 9 unterstützt Datensätze , bei denen es sich um vollständig unveränderliche Typen handelt. Darüber hinaus verfügen Datensätze über With-Ausdrücke zum Erstellen neuer Datensätze aus vorhandenen Datensätzen, um den neuen Status darzustellen.

Judah Gabriel Himango
quelle
1
Ein weiterer Hinweis ist, dass [Pure] seit dem Pre-Release-Drop dieser Woche öffentlich ist, [Mutability (...)] jedoch intern. Wir werden sehen, ob sich dies ändert.
Judah Gabriel Himango
Zu beachten ist auch, ob diese Attribute für die allgemeine Verwendung bestimmt sind oder nur für die Verwendung in den Vertrags-APIs. Ich würde hoffen, dass sie im Allgemeinen nützlich sind, um in einer Codebasis verwendet zu werden, unabhängig davon, ob man die tatsächlichen System.Diagnostics.Contract-APIs verwendet.
Judah Gabriel Himango
72
+1 für die Aktualisierung der Antwort auf eine alte Frage, als sich die Welt veränderte.
Emile
2
@ BartoszKP Wirklich? Ich finde das sehr hilfreich - jede Bearbeitung zeigt einen Punkt in einer Zeitleiste an, und diese Zeitleiste ist immer noch wichtig und relevant, da ältere Versionen des C # -Compilers immer noch verwendet werden (zum Beispiel arbeite ich an einem Projekt, das aus irgendeinem Grund , kann nur in MSVS 2013 kompiliert werden).
Kyle Strand
1
@ BartoszKP Es ist vielleicht nicht optimal, aber ich denke nicht, dass es "verschmutzt" ist.
Kyle Strand
17

Es gibt nicht nur nichts für die Überprüfung von Nebenwirkungen, sondern auch nichts, um zu überprüfen, ob ein Typ unveränderlich ist. Dies ist ein kleinerer Schritt auf demselben Weg, IMO.

Ich glaube nicht, dass in C # 4.0 irgendetwas auf dem Spiel steht (obwohl ich mich leicht irren könnte). Ich hoffe wirklich , dass die Unveränderlichkeit einen Einfluss auf C # 5.0 hat. sicherlich hat Eric Lippert einiges darüber gebloggt, und die Leute bei MS haben ziemlich viel über Parallelität nachgedacht.

Entschuldigung, es ist kein ermutigenderes Bild.

Edit: Judahs Antwort ist deutlich heller ... wäre Framework-Unterstützung gut genug für dich? :) (Ich wäre nicht ganz überrascht, wenn einige Aspekte von Codeverträgen nicht für .NET 4.0 bereit wären, wohlgemerkt - wenn sie die ursprüngliche Version vielleicht relativ klein halten und später verbessern würden.)

Jon Skeet
quelle
Danke Jon. Ihre Einsicht ist immer willkommen :) Ich wollte nur sehen, was in dieser Abteilung los ist.
Joan Venge
1
Ansichten darüber, ob diese Antwort noch nützlich ist oder ob sie im Lichte von Juda gelöscht werden sollte, sind willkommen. Gerne löschen wir es gegebenenfalls.
Jon Skeet
Ich würde es wirklich mögen, wenn die Laufzeit Reinheit und Unveränderlichkeit garantieren würde, genau wie es für die Typensicherheit der Fall ist. Auf diese Weise können Sie eine reine Sprache über der CLR erstellen und C # sicher aufrufen (oder von dort aufgerufen werden).
Tom Lokhorst
@ Jon: Ich denke deine Antwort ist immer noch nützlich.
Joan Venge
Ich denke, Ihre Antwort ist immer noch nützlich. Ich habe gerade meine Antwort aktualisiert, um neu gefundene Informationen aufzunehmen: Es scheint, dass .NET über die Attribute System.Diagnostics.Contracts.PureAttribute und System.Diagnostics.Contracts.Mutability verfügt. VS2010 wird mit einem statischen Analysetool geliefert, das integriert ist, um Reinheit usw. zu erzwingen
Judah Gabriel Himango
14

Im Prinzip ist es einfach zu überprüfen, ob etwas unveränderlich ist und ob dem Code Nebenwirkungen fehlen. Alle Felder der Klassen- / Datenstruktur müssen schreibgeschützt sein und ihr Typ muss ein anderes unveränderliches Objekt sein. Wir brauchen auch eine Möglichkeit, einen Delegierten als "rein" (nebenwirkungsfrei) zu markieren, aber das wäre wahrscheinlich alles möglich.

Das Problem ist jedoch, dass dies oft zu restriktiv ist. In F # schreiben Sie den Code im Allgemeinen in einem nebenwirkungsfreien und unveränderlichen Stil, aber es ist oft vorteilhaft, eine Mutation lokal zu verwenden. Dies beeinträchtigt nicht die Gesamtreinheit (in gewissem Sinne) und erleichtert das Schreiben des Codes erheblich. Es ist jedoch schwierig, dies automatisch zu überprüfen (was bedeutet, dass es sich um ein interessantes theoretisches Problem handelt.)

Zum Beispiel ist es vollkommen in Ordnung, mit Arrays auf "reine" Weise zu arbeiten. Sie können Methoden wie Array.map verwenden , die eine Funktion auf alle Elemente anwenden und ein neues Array zurückgeben, ohne das ursprüngliche zu ändern . Die Funktion mutiert das (neu erstellte) Array, bevor es zurückgegeben wird, aber das Array wird nirgendwo anders mutiert. Dies ist also im Prinzip rein , aber schwer zu überprüfen (und dies ist ein sehr nützliches Programmiermuster in F #).

Ich denke, es gibt viel zu tun, aber ein einfaches Verbot aller Nebenwirkungen ist möglicherweise nicht so gut, wie es scheint. Das Schöne an Verträgen ist, dass sie wahrscheinlich auch in diesem Szenario verwendet werden können.

Tomas Petricek
quelle