‚Delegieren‚System.Action‘nimmt nicht 0 Argumente.‘ Ist das ein C # Compiler Fehler (Lambda-Ausdrücke + zwei Projekte)?

StackOverflow https://stackoverflow.com/questions/4466859

Frage

Betrachten Sie den Code unten. Sieht aus wie perfekt gültige C # -Code oder?

//Project B
using System;
public delegate void ActionSurrogate(Action addEvent);
//public delegate void ActionSurrogate2();
// Using ActionSurrogate2 instead of System.Action results in the same error
// Using a dummy parameter (Action<double, int>) results in the same error

// Project A
public static class Class1 {
    public static void ThisWontCompile() {
        ActionSurrogate b = (a) =>
                            {
                                a(); // Error given here
                            };
    }
}

erhalte ich einen Compiler-Fehler ‚Delegate‚Aktion‘nicht 0 Argumente übernimmt.‘ an der angegebenen Stelle der (Microsoft) C # 4.0-Compiler. Beachten Sie, dass Sie ActionSurrogate in einem anderen Projekt für diesen Fehler zu manifestieren erklären haben.

Es wird immer interessanter:

// Project A, File 1
public static class Class1 {
    public static void ThisWontCompile() {
        ActionSurrogate b = (a) => { a(); /* Error given here */ };
        ActionSurrogate c = (a) => { a(); /* Error given here too */ };
        Action d = () => { };
        ActionSurrogate c = (a) => { a(); /* No error is given here */ };
    }
}

Habe ich stolpern auf einen C # -Compiler Fehler hier?

Beachten Sie, dass dies ein ziemlich ärgerlich Fehler für jemanden, das lambda viel mag mit und versuchen, eine Datenstruktur Bibliothek für die zukünftige Verwendung zu schaffen ... (me)

EDIT:. Entfernt falsch empfangenen Fall

ich kopiert und gestrippt mein ursprüngliches Projekt auf das Minimum, dies zu verwirklichen. Das ist buchstäblich der gesamte Code in meinem neuen Projekt.

War es hilfreich?

Lösung

Dies ist wahrscheinlich ein Problem mit Typ inferance, apperently der Compiler folgert a als Action<T> statt Action (es könnte denken, a ActionSurrogate ist, was die Action<Action>> Signatur passen würde). Versuchen Sie unter Angabe der Art der a ausdrücklich:

    ActionSurrogate b = (Action a) =>
                        {
                            a();
                        };

Wenn dies nicht der Fall ist -. Könnte Ihr Projekt für alle selbstdefinierten Action Delegierten überprüfen um unter einem Parameter

Andere Tipps

FINAL UPDATE:

Der Fehler ist in C # 5. Apologies erneut für die Unannehmlichkeiten, und danke für den Bericht fest.


Original-Analyse:

kann ich das Problem mit den Kommandozeilen-Compiler reproduzieren. Es sieht auf jeden Fall wie ein Fehler. Es ist wahrscheinlich meine Schuld; Das tut mir leid. (Ich schrieb alle von der Lambda-to-Delegaten Umwandlung Prüfcodes.)

Ich bin gerade in einem Café, und ich habe keinen Zugriff auf die Compiler-Quellen von hier. Ich werde versuchen, einige Zeit zu finden, das morgen in dem Debug-Build zu reproduzieren und sehen, ob ich arbeiten können, was los ist. Wenn ich nicht die Zeit finden, werde ich im Büro sein, bis nach Weihnachten.

Ihre Beobachtung, dass eine Variable vom Typ Aktion Einführung verursacht das Problem zu verschwinden ist äußerst interessant. Der Compiler unterhält viele Caches für beide Leistungsgründen und für die Analyse der Sprachspezifikation erforderlich. Lambdas und lokale Variablen insbesondere haben viele komplexe Caching-Logik. Ich würde so viel wie ein Dollar Wette bereit sein, dass einige Cache hier in falsch initialisiert oder gefüllt werden, und dass die Verwendung der lokalen Variablen Füllungen in dem richtigen Wert im Cache.

Danke für den Bericht!

UPDATE: Ich bin jetzt auf dem Bus und es kam nur zu mir; Ich glaube, ich weiß genau, was falsch ist. Der Compiler ist faul , vor allem, wenn sie mit Typen zu tun, die kamen aus den Metadaten. Der Grund dafür ist, dass es Hunderttausende von Arten in den genannten Baugruppen sein könnte, und es besteht keine Notwendigkeit zu laden Informationen über alle von ihnen. Du wirst weit weniger als 1% von ihnen wahrscheinlich verwenden, so lassen Sie uns nicht viel Zeit und Speicherlade Sachen verschwenden sind Sie nie benutzen würde. In der Tat geht die Faulheit tiefer als das; eine Art durchläuft mehrere „Stufen“, bevor es verwendet werden kann. Zuerst sein Name bekannt ist, dann sein Basistyp, dann, ob seine Hierarchie Basistyp ist begründet (azyklisch, usw.), dann Einschränkungen ihrer Typparameter, dann ihre Mitglieder, dann, ob die Mitglieder sind begründet (das Überschreiben Überschreiben etwas von der gleichen Signatur, und so weiter.) ich wette, dass die Umwandlungslogik die Methode aufzurufen versagt, die „sicherstellen, dass die Typen aller Delegierten Parameter haben ihre Mitglieder bekannt“, sagt vor es überprüft die Signatur des Delegaten invoke für Kompatibilität. Aber der Code, der wahrscheinlich eine lokale Variable macht hat das tun. Ich denke, dass bei der Umsetzung Prüfung könnte der Aktionstyp nicht einmal eine invoke-Methode hat, soweit der Compiler geht.

Wir werden in Kürze erfahren.

UPDATE: Meine psychischen Kräfte stark sind heute Morgen. Bei Versuchen, die Überladungsauflösung zu bestimmen, ob es eine „Invoke“ Methode des Delegierten Typ ist, der Null Argumente annimmt, findet es Null Invoke Methoden von zu wählen. Wir sollten sicherstellen, dass die Delegattyp Metadaten vollständig geladen ist, bevor wir die Überladungsauflösung tun. Wie seltsam, dass diese so lange unbemerkt geblieben ist; es Repros in C # 3.0. Natürlich ist repro es nicht in C # 2.0, nur weil es keine lambdas waren; anonyme Methoden in C # 2.0 benötigen Sie die Art, ausdrücklich zu erwähnen, die eine lokale schafft, die wir lädt die Metadaten kennen. Aber ich könnte mir vorstellen, dass die Ursache des Fehlers - dass die Überladungsauflösung nicht Laden Metadaten für die invoke zwingt -. Zurück zu C geht # 1.0

Wie auch immer, faszinierende Fehler, danke für den Bericht. Offensichtlich haben Sie eine Abhilfe bekommen. Ich werde QA es haben Spur von hier und wir werden versuchen, es für C repariert # 5 (Wir haben das Fenster für Service Pack 1, das bereits in der beta ist.)

    public static void ThisWontCompile()
        {
            ActionSurrogate b = (Action a) =>
            {
                a();
            };


        }

Dies kompiliert. Einige Glitch mit dem Compiler seiner nicht in der Lage, die Aktionsdelegate zu finden, ohne Parameter. Deshalb sollten Sie die Fehlermeldung erhalten.

public delegate void Action();
public delegate void Action<T>();
public delegate void Action<T1,T2>();
public delegate void Action<T1,T2,T3>();
public delegate void Action<T1,T2,T3,T4>();
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top