Domanda

Sono nuovo a tutte le funzionalità anonime e ho bisogno di aiuto.Ho ottenuto quanto segue per funzionare:

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));
}

Ma questo è totalmente brutto e mi piacerebbe che l'interno del Do fosse un metodo anonimo o anche un lambda se possibile.Ho provato:

Expect.Call(delegate { _dao.Save(t); }).Do(delegate(Transaction t2) { t2.Message = "I drink goats blood"; });

E

Expect.Call(delegate { _dao.Save(t); }).Do(delegate { t.Message = "I drink goats blood"; });

ma questi mi danno

Impossibile convertire il metodo anonimo nel tipo "System.Delegate" perché non è un tipo delegato** errori di compilazione.

Che cosa sto facendo di sbagliato?


A causa di ciò che ha pubblicato Mark Ingram, sembra che la risposta migliore, anche se nessuno lo abbia detto esplicitamente, è fare questa:

public delegate void FakeSave(Transaction t);

Expect.Call(delegate { _dao.Save(t); }).Do( new FakeSave(delegate(Transaction t2) { t.Message = expected_msg; }));
È stato utile?

Soluzione

Questo è un messaggio di errore ben noto.Controlla il link sottostante per una discussione più dettagliata.

http://staceyw1.wordpress.com/2007/12/22/they-are-anonymous-methods-not-anonymous-delegates/

Fondamentalmente devi solo mettere un cast davanti al tuo delegato anonimo (la tua espressione lambda).

Nel caso in cui il collegamento non dovesse funzionare, ecco una copia del post:

Sono metodi anonimi, non delegati anonimi.
Pubblicato il 22 dicembre 2007 da staceyw1

Non è solo un punto di discussione perché vogliamo essere difficili.Ci aiuta a ragionare su cosa sta succedendo esattamente.Per essere chiari, non esiste *non esiste un delegato anonimo.Non esistono (non ancora).Sono "metodi anonimi" - periodo.Importa come pensiamo a loro e a come ne parliamo.Diamo un'occhiata all'istruzione del metodo anonimo "delegate () {…}".Questa è in realtà due operazioni diverse e quando ci pensiamo in questo modo, non saremo mai più confusi.La prima cosa che fa il compilatore è creare il metodo anonimo sotto le copertine usando la firma delegata inferita come firma del metodo.Non è corretto dire che il metodo è "senza nome" perché ha un nome e il compilatore lo assegna.È solo nascosto dalla vista normale.La prossima cosa che fa è creare un oggetto delegato del tipo richiesto per avvolgere il metodo.Questo si chiama delegato inferenza e può essere la fonte di questa confusione.Affinché questo funzioni, il compilatore deve essere in grado di capire (cioèInfer) quale tipo delegato creerà.Deve essere un tipo di cemento noto.Lascia che scriva del codice per capire perché.

private void MyMethod()
{
}

Non compila:

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 riga 1 non si compila perché il compilatore non può dedurre alcun tipo di delegato.Può chiaramente vedere la firma che desideriamo, ma non esiste un tipo di delegato in cemento che il compilatore può vedere.Potrebbe creare un tipo anonimo di delegato di tipo per noi, ma non funziona così.La riga 2 non si compila per un motivo simile.Anche se il compilatore conosce la firma del metodo, non gli stiamo dando un tipo di delegato e non sceglierà solo uno che accadrebbe funzionare (non quali effetti collaterali potrebbero avere).La riga 3 non funziona perché abbiamo intenzionalmente mancata la firma del metodo con un delegato che ha una firma diversa (come prende WaitCallback e oggetto).

Compila:

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.

Al contrario, questi funzionano.La riga 1 funziona perché diciamo al compilatore quale tipo di delegato usa e corrispondono, quindi funziona.La riga 5 funziona per lo stesso motivo.Nota Abbiamo usato la forma speciale di "delegato" senza i parenti.Il compilatore deduce la firma del metodo dal cast e crea il metodo anonimo con la stessa firma del tipo delegato dedotto.La riga 6 funziona perché il myMethod () e l'azione utilizzano la stessa firma.

Spero che aiuti.

Vedi anche: http://msdn.microsoft.com/msdnmag/issues/04/05/C20/

Altri suggerimenti

Quello che ha detto Marco.

Il problema è che Do accetta un parametro Delegate.Il compilatore non può convertire i metodi anonimi in Delegate, solo un "tipo delegato", ad es.un tipo concreto derivato da Delegate.

Se la funzione Do avesse eseguito Azione<>, Azione<,> ...eccetera.sovraccarichi, non avresti bisogno del gesso.

Il problema non riguarda la definizione del delegato, è che il parametro del metodo Do() è di tipo System.Delegate e il tipo delegato generato dal compilatore (FakeSave) non viene convertito implicitamente in System.Delegate.

Prova ad aggiungere un cast davanti al tuo delegato anonimo:

Expect.Call(delegate { _dao.Save(t); }).Do((Delegate)delegate { t.Message = "I drink goats blood"; });

Prova qualcosa come:

Expect.Call(delegate { _dao.Save(t); }).Do(new EventHandler(delegate(Transaction t2) { t2.CheckInInfo.CheckInMessage = "I drink goats blood"; }));

Nota l'EventHandler aggiunto attorno al delegato.

MODIFICARE:potrebbe non funzionare poiché le firme delle funzioni di EventHandler e del delegato non sono le stesse...La soluzione che hai aggiunto in fondo alla tua domanda potrebbe essere l'unico modo.

In alternativa, puoi creare un tipo delegato generico:

public delegate void UnitTestingDelegate<T>(T thing);

In modo che il delegato non sia specifico della transazione.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top