Wie andere bemerkt haben, besteht das Problem darin, dass Delegattypen nicht "strukturell" sind. Das heißt, sie haben keine Äquivalenz basierend auf ihrer "Struktur".
Nun, das ist wohl eine gute Sache für einige Arten. Wenn Sie
haben %Vor%und
%Vor%Offensichtlich wäre es ein Fehler, Instanzen von MyRectangle Variablen von YourRectangle zuzuweisen, nur weil sie beide aus vier Ints bestehen. Die Semantik der Ints ist unterschiedlich und daher sind die Typen nicht äquivalent.
Das gilt theoretisch auch für die Delegierten. Du könntest
haben %Vor%wobei eine "reine" Funktion ohne Nebeneffekte und die gleiche Ausgabe bei gleicher Eingabe ist. Da jeder Pure logisch ein Func ist, aber nicht jeder Func ein Pure ist, sollte es keine strukturelle Typisierung zwischen ihnen geben.
In der Praxis unterstützt das Typsystem natürlich Begriffe wie "pure function" nicht sehr gut. Und in der Praxis ist die überwiegende Mehrheit der Versuche, zwischen den Delegattypen zu konvertieren, vollkommen sicher: Umwandlung von Func<int, bool>
in Predicate<int>
und so weiter.
Also, zwei Dinge, ein Blick nach hinten und ein Blick nach vorne. Rückwärts: Wenn wir es noch einmal machen müssten, würden die Delegierten wahrscheinlich strukturell in die CLI eingetippt werden. Sie wissen nicht immer, welche Funktionen nützlich sein werden, wenn Sie ein brandneues Framework entwerfen, und nicht-strukturelle Delegattypen haben sich bisher als nicht so nützlich erwiesen wie vielleicht erwartet. Vorwärts: Ich erwarte, dass in zukünftigen CLR-Versionen mehr Funktionen angezeigt werden, die eine strukturiertere Typisierung ermöglichen. Das "no pia" -Feature in C # 4 zum Beispiel geht darum, zwei Typen, die semantisch und strukturell gleich sind, aber in verschiedenen Assemblies definiert sind, logisch strukturell zu vereinheitlichen.
Sie bemerken, dass Action
ein Typ ist und das "Lambda" in Ihrem zweiten Beispiel nicht.
Wahrscheinlich sind sie gleich, aber Sie verwenden einen konkreten Framework-Typ, wenn Sie Action
verwenden, während der Compiler die Signatur des Lambda ableitet.
EDIT: um klar zu sein:
Aktion ist ein Delegattyp, der not
ein ThreadStart-Delegat ist. Sie können also den Lambda-Ausdruck beiden zuweisen, aber Sie können nicht beide verwenden, um einen Thread zu starten.
Im zweiten Beispiel geben Sie dem Compiler die Möglichkeit, den Typ des Delegaten abzuleiten, und ohne große Überraschung kann er den Lambda-Ausdruck dem Typ ThreadStart zuweisen.
Delegierte mit der gleichen Unterschrift sind in den Augen der CLR nicht gleich - sie sind völlig unterschiedliche Typen.
Die Grundform dieses Fehlers ist:
%Vor%So könnten Sie Ihre erste Probe "lösen", indem Sie den richtigen Delegattyp verwenden:
%Vor%Ich denke, das folgende Wort in Abschnitt 26.3.1 der C # -Sprachspezifikation ist wichtig:
Ähnlich wie bei einem anonymer Methodenausdruck, a Lambda-Expression wird als a eingestuft Wert mit speziellen Konvertierungsregeln. Der Wert hat keinen Typ, kann aber implizit in a konvertiert werden kompatibler Delegattyp Insbesondere ist ein Delegattyp D kompatibel mit einem Lambda-Ausdruck L zur Verfügung gestellt:
[List elided]
Was verhindert, dass Code wie dieser kompiliert wird:
%Vor%Was zu:
führt %Vor%Wird vom Compiler abgelehnt, wenn Konvertierungen von einem Delegattyp zu einem anderen nicht zulässig sind, auch wenn ihre Signaturen kompatibel sind. Erzwingen:
%Vor%Welches kompiliert ohne Probleme.
Irrelevantes Bonus-Feature: Bei ersten Usability-Tests auf dem ersten Apple Mac wurde ein Problem mit der ersten Version der OK-Schaltfläche in den Dialogen festgestellt, die eine serifenlose Schriftart verwendeten. Die Benutzer klickten stattdessen oft auf "Abbrechen", mit sichtbarer Angst. Nach mehreren Interviews gab ein Nutzer schließlich das Problem zu: "Ich hasse es, wenn ein Computer mich einen Dolt nennt!"
Nun, ein Compiler, der dich vielleicht als Dummkopf bezeichnet, ist nicht so irrelevant:)
Weil der Threadstart ein separater Delegattyp ist und Action
nicht in ThreadStart
konvertiert werden kann.
Dieser Fall funktioniert, weil hier Ihr Lambda vom Compiler als ThreadStart behandelt wird:
%Vor%Tags und Links c# multithreading action delegates