Konvertieren Sie die Delegierten zu einer anonymen Methode oder Lambda
-
09-06-2019 - |
Frage
Ich bin neu in alle anonymen Funktionen und benötige Hilfe. Ich habe folgendes bekommen zu arbeiten:
public void FakeSaveWithMessage(Transaction t)
{
t.Message = "I drink goats blood";
}
public delegate void FakeSave(Transaction t);
public void SampleTestFunction()
{
Expect.Call(delegate { _dao.Save(t); }).Do(new FakeSave(FakeSaveWithMessage));
}
Das ist aber total hässlich, und ich möchte das Innere des Do habe eine anonyme Methode oder auch ein Lambda sein, wenn es möglich ist. Ich habe versucht:
Expect.Call(delegate { _dao.Save(t); }).Do(delegate(Transaction t2) { t2.Message = "I drink goats blood"; });
und
Expect.Call(delegate { _dao.Save(t); }).Do(delegate { t.Message = "I drink goats blood"; });
aber diese geben mir
Kann nicht anonyme Methode konvertieren ‚System.Delegate‘ zu geben, weil es kein Delegattyp ist ** Fehler kompiliert werden.
Was mache ich falsch?
Aufgrund dessen, was Mark Ingram geschrieben, scheint die beste Antwort, wenn auch niemand gesagt, es ausdrücklich, ist dies zu tun:
public delegate void FakeSave(Transaction t);
Expect.Call(delegate { _dao.Save(t); }).Do( new FakeSave(delegate(Transaction t2) { t.Message = expected_msg; }));
Lösung
Das ist eine bekannte Fehlermeldung. Überprüfen Sie den folgenden Link für eine ausführlichere Diskussion.
Im Grunde brauchen Sie nur eine Besetzung vor Ihrem anonymen Delegaten setzen (Ihr Lambda-Ausdruck).
die Verbindung überhaupt Bei geht, ist hier eine Kopie der Post:
Sie sind Anonyme Methoden, nicht Anonymous Delegierten.
Veröffentlicht am 22. Dezember 2007 von staceyw1Es ist nicht nur ein Gesprächsthema, denn wir wollen, schwierig sein. Es hilft uns, Grund zu wissen, was genau vor sich geht. Um klar zu sein, gibt es nicht so etwas * als anonymer Delegierter. Sie tun es nicht existiert (noch nicht). Sie sind „Anonymous Methods“- Periode Es spielt eine Rolle in wie. wir von ihnen denken und wie wir sprechen über Sie. Werfen wir einen Blick auf die anonyme Methode Anweisung „delegieren () {...}“. Das ist eigentlich zwei verschiedene Operationen und wenn wir denken an sie Auf diese Weise werden wir nie verwechselt werden nochmal. Das erste, was der Compiler tut, ist die anonyme Methode erstellen unter der Decke unter Verwendung der abgeleiteten Signatur als Verfahren delegieren Unterschrift. Es ist nicht richtig zu sagen, das Verfahren ist „unnamed“, weil es hat einen Namen und den Compiler ordnet sie. Es ist nur versteckt aus normale Ansicht. Das nächste, was es tut ein Delegatobjekt der ist erstellen erforderliche Art des Verfahrens zu wickeln. Diese Delegierte Inferenz und kann aufgerufen die Quelle dieser Verwirrung. Zum dies funktioniert, muss der Compiler sein Lage, herauszufinden, (d infer), was Delegattyp wird es schaffen. Es hat ein bekannter konkreter zu sein. Lassen schreiben einige Code, um zu sehen, warum.
private void MyMethod()
{
}
Ist nicht kompilieren:
1) Delegate d = delegate() { }; // Cannot convert anonymous method to type ‘System.Delegate’ because it is not a delegate type
2) Delegate d2 = MyMethod; // Cannot convert method group ‘MyMethod’ to non-delegate type ‘System.Delegate’
3) Delegate d3 = (WaitCallback)MyMethod; // No overload for ‘MyMethod’ matches delegate ‘System.Threading.WaitCallback’
Zeile 1 nicht kompiliert, da die Compiler kann keine Delegierten schließen Art. Es kann deutlich die Unterschrift sehen wir wünschen, aber es gibt keine konkreten Geben Sie delegieren kann der Compiler sehen. Es könnte eine anonyme Art von erstellen Geben Sie Delegat für uns, aber es funktioniert nicht wie das funktioniert. Linie 2 nicht kompilieren aus einem ähnlichen Grund. Sogar obwohl weiß der Compiler die Methode Unterschrift, wir geben es nicht Typ delegieren und es ist nicht nur gehen um eine auswählen, die funktionieren würde passieren (Nicht, welche Nebenwirkungen das könnte haben). Linie 3 nicht, weil Arbeit wir nicht übereinstimmen absichtlich die Methode Signatur mit einem Delegieren einer mit andere Signatur (als WaitCallback nimmt und Objekt).
Kompiliert:
4) Delegate d4 = (MethodInvoker)MyMethod; // Works because we cast to a delegate type of the same signature.
5) Delegate d5 = (Action)delegate { }; // Works for same reason as d4.
6) Action d6 = MyMethod; // Delegate inference at work here. New Action delegate is created and assigned.
Im Gegensatz dazu diese Arbeit. Zeile 1 Werk weil wir sagen dem Compiler was delegieren Typ zu verwenden und sie übereinstimmen, so dass es funktioniert. Linie 5 arbeitet für die gleicher Grund. Beachten wir die besondere verwendet Form „delegieren“ ohne die Pars. Der Compiler folgert das Verfahren Unterschrift von der Besetzung und schafft die anonyme Methode mit dem gleichen Signatur als die abgeleiteten Delegierten Art. Line 6 funktioniert, weil die MyMethod () und Aktion verwenden gleiche Unterschrift.
Ich hoffe, das hilft.
Siehe auch: http://msdn.microsoft.com/msdnmag/issues/04/05/ C20 /
Andere Tipps
Was Mark sagte.
Das Problem ist, dass Do einen Delegierten Parameter annimmt. Der Compiler kann nicht die anonymen Methoden konvertieren zu delegieren, nur einen „Delegattyp“ heißt konkreter von Delegierten abgeleitet.
Wenn die Do-Funktion Aktion hatte die <>, Aktion <,> ... usw. Überlastungen, würden Sie nicht die Besetzung müssen.
Das Problem ist nicht mit Ihrem Delegat Definition, dann ist es, dass der Parameter des Do () Methode des Typs System.Delegate ist, und der Compiler generiert Delegattyp (FakeSave) konvertiert nicht implizit System.Delegate.
Versuchen Sie, eine Guss vor Ihrem anonymen Delegaten hinzu:
Expect.Call(delegate { _dao.Save(t); }).Do((Delegate)delegate { t.Message = "I drink goats blood"; });
Versuchen Sie so etwas wie:
Expect.Call(delegate { _dao.Save(t); }).Do(new EventHandler(delegate(Transaction t2) { t2.CheckInInfo.CheckInMessage = "I drink goats blood"; }));
Beachten Sie die zusätzlichen Eventhandler um die Delegierten.
EDIT:. Könnte nicht funktionieren, da die Funktion Unterschriften von Eventhandler und den Delegierten nicht gleich sind ... Die Lösung, die Sie auf der Unterseite Ihrer Frage hinzugefügt werden, der einzige Weg sein
Alternativ können Sie einen allgemeinen Delegattyp erstellen:
public delegate void UnitTestingDelegate<T>(T thing);
Damit die Delegierten nicht Transaktion spezifisch ist.