Convertissez ce délégué en une méthode anonyme ou lambda
Je suis nouveau dans toutes les fonctionnalités anonymes et j'ai besoin d'aide. J'ai obtenu ce qui suit pour travailler:
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));
}
Mais c'est totalement Moche et j'aimerais avoir l'intérieur du Do pour être une méthode anonyme ou même un lambda si c'est possible. J'ai essayé:
Expect.Call(delegate { _dao.Save(t); }).Do(delegate(Transaction t2) { t2.Message = "I drink goats blood"; });
Et
Expect.Call(delegate { _dao.Save(t); }).Do(delegate { t.Message = "I drink goats blood"; });
Mais ceux-ci me donnent
Impossible de convertir la méthode anonyme en type ' System.Delegate ' parce que ce n'est pas un type de délégué** erreurs de compilation.
Ce que je fais de mal?
En raison de ce que Mark Ingram a posté, il semble que la meilleure réponse, bien que personne ne l'ait explicitement dit, est de faire ceci:
public delegate void FakeSave(Transaction t);
Expect.Call(delegate { _dao.Save(t); }).Do( new FakeSave(delegate(Transaction t2) { t.Message = expected_msg; }));
4 réponses
C'est un message d'erreur bien connu. Consultez le lien ci-dessous pour une discussion plus détaillée.
Http://staceyw1.wordpress.com/2007/12/22/they-are-anonymous-methods-not-anonymous-delegates/
Fondamentalement, vous avez juste besoin de mettre un cast devant votre délégué anonyme (votre expression lambda).
Dans le cas où le lien tombe en panne, voici une copie du message:
Ce sont des méthodes anonymes, pas Les Délégués Anonymes.
Poster le 22 décembre 2007 par staceyw1Ce n'est pas seulement un point de discussion parce que nous voulons être difficile. Il nous aide à la raison à propos de ce qui se passe exactement. Pour être clair, il n'y a pas une telle chose en tant que délégué anonyme. Ils n'ont pas existe pas (pas encore). Ils sont "anonymes Les méthodes" de la période. Il importe dans Comment nous pensons à eux et comment nous parlons ils. Permet de jeter un coup d'oeil à la déclaration de méthode anonyme " délégué() {…}". C'est en fait deux les opérations et les quand on pense à elle de cette façon, nous ne serons jamais confus Encore une fois. La première chose que le compilateur est-ce que c'est créer la méthode anonyme sous les couvertures en utilisant le déduit déléguer la signature comme méthode signature. Il n'est pas correct de dire la méthode est "sans nom" car elle ne avoir un nom et le compilateur il l'attribue. Il est juste caché de en mode normal. La prochaine chose qu'il fait est de créer un objet délégué du type requis pour envelopper la méthode. Ce est appelé délégué inférence et peut être la source de cette confusion. Pour cela fonctionne, le compilateur doit être capable de comprendre (c'est-à-dire déduire) quoi type de délégué qu'il va créer. Il a être un type de béton connu. Laisser écrire du code pour voir pourquoi.
private void MyMethod()
{
}
Ne compile pas:
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’
La Ligne 1 ne se compile pas car le compilateur ne peut en déduire aucun délégué type. Il peut clairement voir la signature nous désirons, mais il n'y a pas de béton le type de délégué que le compilateur peut voir. Il pourrait créer un type anonyme de tapez delegate pour nous, mais ce n'est pas le cas travailler comme ça. La ligne 2 n'est pas compiler pour une raison similaire. Même bien que le compilateur connaisse la méthode signature, nous ne lui donnons pas un type de délégué et il ne va pas seulement pour choisir un qui arriverait à travailler (pas quels effets secondaires qui pourraient avoir). Ligne 3 ne fonctionne pas parce que nous avons délibérément mis en correspondance la méthode signature avec un délégué ayant un signature différente (comme WaitCallback prend et l'objet).
Compile:
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.
En revanche, ces travaux. La ligne 1 fonctionne parce que nous disons au compilateur quoi type de délégué à utiliser et ils correspondent, de sorte qu'il fonctionne. Ligne 5 fonctionne pour le même raison. Remarque: nous utilisons la forme de "délégué" sans parens. Le compilateur déduit la méthode signature de la distribution et crée la méthode anonyme avec le même signature présumées délégué type. La ligne 6 fonctionne parce que le MyMethod () et Action utilisent même signature.
J'espère que cela aide.
Voir Aussi: http://msdn.microsoft.com/msdnmag/issues/04/05/C20/
Ce que Mark a dit.
Le problème est que Do prend un paramètre Delegate. Le compilateur ne peut pas Convertir les méthodes anonymes en Delegate, seulement un "type de délégué", c'est-à-dire un type concret dérivé de Delegate.
Si cette fonction Do avait pris Action, Action... etc. surcharges, vous n'auriez pas besoin du plâtre.
Le problème n'est pas avec votre définition de délégué, c'est que le paramètre de la méthode Do() est de type System.Delegate, et le type de délégué généré par le compilateur (FakeSave) ne se convertit pas implicitement en système.Délégué.
Essayez d'ajouter une distribution devant votre délégué anonyme:
Expect.Call(delegate { _dao.Save(t); }).Do((Delegate)delegate { t.Message = "I drink goats blood"; });
Essayez quelque chose comme:
Expect.Call(delegate { _dao.Save(t); }).Do(new EventHandler(delegate(Transaction t2) { t2.CheckInInfo.CheckInMessage = "I drink goats blood"; }));
Notez le Gestionnaire D'événements ajouté autour du délégué.
EDIT: peut ne pas fonctionner car les signatures de fonction de EventHandler et du délégué ne sont pas les mêmes... La solution que vous avez ajoutée au bas de votre question peut être le seul moyen.
Vous pouvez également créer un type de délégué générique:
public delegate void UnitTestingDelegate<T>(T thing);
Afin que le délégué ne soit pas spécifique à la Transaction.