Come passare arbitraria di un metodo (o delegato) come parametro di una funzione?

Ho bisogno di essere in grado di passare arbitraria di un metodo per alcune funzioni myFunction:

void myFunction(AnyFunc func) { ... }

Dovrebbe essere possibile eseguire con altri statico, istanza, pubblico o privato, metodi o anche delegati:

myFunction(SomeClass.PublicStaticMethod);
myFunction(SomeObject.PrivateInstanceMethod);
myFunction(delegate(int x) { return 5*x; });

Passati metodo può avere qualsiasi numero di parametri e di qualsiasi tipo di ritorno. Dovrebbe anche essere possibile conoscere il numero effettivo dei parametri e dei tipi in myFunction via di riflessione. Che cosa sarebbe AnyFunc in myFunction definizione di venire incontro a queste esigenze? Non è accettabile avere diverse versioni di overload del myFunction.

  • Che cosa si aspetta da passare al metodo se si dispone di parametri? Sembra che dovrebbe essere la conversione di qualsiasi metodo è nessun parametro/void ritorno (aka Action) prima di passare a questo metodo.
  • myFunction analizzare i parametri della funzione di controllo contro alcuni database esterno e chiamare con valori necessari o negativo se nessuna voce corrispondente nel database è trovato.
  • Questo è molto preoccupante design, in cui si sta essenzialmente il trattamento di codice come dati. Si dovrebbe prendere in considerazione cercando di ridisegnare questo, in modo tale che il codice è statico.
  • Sì. Ci sarà un compilatore embedded che creare il codice da dati. Sono consapevole dei rischi per la sicurezza, ma questo è ciò di cui abbiamo bisogno nel nostro progetto.
  • no, non è preoccupante design, è solo un altro esempio di design — trattamento di funzioni come dati. Common Lisp, Haskell, queste lingue sono costruita intorno ad un’architettura. In particolare C#: sto scrivendo una funzione che prende un testo, come primo argomento, e applica una funzione dal secondo argomento ad un newline. Pensi veramente che sia una cattiva idea? Si rende un design trasparente.
  • Che a che fare con i metodi di una nota firma. Avendo una funzione incognita che accetta una stringa e restituisce un tipo specifico di conseguenza, senza conoscere la sua implementazione, non è certamente di cattivo design.

 

2 Replies
  1. 6

    Il Delegate tipo è il supertipo di tutti gli altri tipi di delegati:

    void myFunction(Delegate func) { ... }

    Quindi, func.Metodo vi darà un MethodInfo oggetto è possibile utilizzare per ispezionare il tipo di ritorno e i tipi di parametro.

    Quando si chiama la funzione si dovrà specificare in modo esplicito il tipo di delegato che si desidera creare:

    myFunction((Func<int, int>) delegate (int x) { return 5 * x; });

    Un’idea di ciò che si sta cercando di realizzare a un livello superiore sarebbe buona, come questo approccio può non essere l’ideale.

    • Vorrei effettuare la chiamata sito il più semplice possibile e nascondere il grintoso dettagli all’interno della biblioteca. Qualsiasi modo per specificare il myFunction in modo che gli utenti non hanno bisogno di esprimere le loro delegati?
    • Il sito di chiamata non può essere reso più semplice, come il compilatore deve alcuni di cemento tipo delegato per creare un’istanza di. Se si desidera accettare “qualsiasi tipo di delegato”, quindi il chiamante deve specificare un tipo di delegato stessi. (Per esempio, dato il delegato anonimo delegate () { }, sia Action e ThreadStart sono compatibili delegato tipi-come è il compilatore di sapere quale creare?)
    • Grazie. Credo che la mia risposta di allora. Che non è possibile. Grazie.
    • Ma perché compilatore bisogno di sapere esatto tipo di delegato? Non è sufficiente solo per sapere tipi di parametro specificato nel delegato-sintassi? È il tipo del valore di ritorno è un problema? Non compilatore derivare dal corpo?
    • È come cercare di costruire un oggetto e chiede: “non è sufficiente conoscere il tipo di argomenti il costruttore prende?” No, non lo è, perché ci sono molti tipi nel quadro che hanno lo stesso costruttore firma. È necessario specificare uno. Esperimento di pensiero: date le definizioni delegate void A(); delegate void B();, come si aspetta il compilatore di dedurre il tipo di espressione delegate () {} con Delegate di essere solo un contestuale indizio sul tipo di espressione?
    • La ragione di solito si può omettere il tipo è a causa del tipo di inferenza. Se si dispone di void Foo(Func<int, int> func); e si scrive Foo(x => x*2); il compilatore sa che il tipo desiderato di espressione lambda è Func<int, int>. C’è una conversione implicita da lambda/anonymous-metodi per uno specifico tipo di delegato. Non c’è conversione implicita di Delegate.
    • Puoi spiegarti meglio la sintassi significato myFunction((Func<int, int>) delegate (int x) { return 5 * x; }); linea? Senza l’ (Func<int, int>) la sezione non è anche un tipo di delegato…
    • int>) è un cast per un tipo di delegato. Questo dà il compilatore contesto sufficienti per dedurre che tipo di anonimo delegato deve essere Func<int, int>.
    • a quanto ho capito delegate (int x) { return 5 * x; } è fondamentalmente (risolto) come metodo. Così, non è un delegato, in modo che il cast per lo specifico tipo di delegato come hai detto. Se ho capito bene questa è una sintassi per definire un metodo anonimo.
    • Che per lo più corretta, ma un po ‘ più complesso. Le informazioni contestuali su che tipo di delega è previsto, possono influenzare la compilazione del delegato. Per esempio, si può altrettanto facilmente dire (Func<int, float>) delegate (int x) { return 5 * x; } e improvvisamente il delegato si riferisce a un metodo che restituisce float — contestuale tipo di delegato ha informato il compilatore che il tipo di ritorno del metodo anonimo dovrebbe essere! Vedi qui

  2. 0

    Il metodo accetta un Delegate, piuttosto che di un particolare delegato:

    void myFunction(Delegate func)
    {
    
    }
    • Come in risposta cdhowie, sarebbe necessario casting delegato per uno specifico tipo di delegato o Func<…>. Vorrei evitare che.
    • E, come ha detto, non e ‘ possibile.

Lascia un commento