Qual è la differenza in questi due esempi di codice c #

1

Qualcuno può spiegarmi perché uno è necessariamente migliore dell'altro?

int M()
{
    int y;
    LocalFunction();
    return y;

    void LocalFunction() => y = 0;
}

Versus

int M()
{
    return LocalFunction();
}

int LocalFunction() {
    return 0;
}

Non ho intenzione di usare l'espressione lambda vs solo facendo un'altra funzione chiara. Qual è il vantaggio dell'uso delle espressioni lambda?

Scusa l'esempio troppo semplicistico.

    
posta Kyle Johnson 05.11.2018 - 18:34
fonte

3 risposte

4

Il tuo esempio è un po 'troppo semplicistico per mostrare un po' della potenza delle funzioni locali. Prendi qualcosa di simile ad esempio:

class Processor
{
    public void func(IEnumerable<MyObject> objectsToProcess)
    {
        foreach (var obj in objectsToProcess)
        {
            if (obj.IsFoo())
            {
                processEntity(obj);
                obj.PostProcessFunction();
            }
            else if (obj.IsBar())
            {
                obj.DoSomeOtherPreProcessingThings();
                processEntity(obj);
            }
            else if (obj.IsBaz())
            {
                obj.Frobinate();
            }
            else
            {
                obj.Slobrify();
                processEntity(obj);
                obj.Zorpalize();
            }
        }

        void processEntity(MyObject obj) => (obj) {
            //lots of code here you don't want to replicate
        };
    }

    //lots of other public and private methods here
}

Supponiamo che la funzione processEntity abbia un bel po 'di codice, qualcosa che non vorresti replicare. In quanto tale, ha perfettamente senso metterlo in una funzione.

Ma che tipo di modificatori di accesso dovrebbe avere? Diciamo anche che la funzione processEntity non verrà mai chiamata dallo spazio pubblico, quindi rendiamola privata. Ma diciamo anche che non verrà mai chiamato da nessun'altra funzione membro. Dovrebbe essere ancora privato, ma può creare un po 'di problemi di manutenzione. Se vuoi cambiare questa funzione privata, devi assicurarti che non venga chiamata da nessun'altra parte (non particolarmente difficile con gli IDE moderni, ma comunque un carico cognitivo di cui devi occuparti). Inoltre lascia aperta la possibilità che lo sviluppo futuro utilizzi quella funzione, possibilmente in modo tale da rompere le cose o in modi che non gestiscono molte sottigliezze

Usando una funzione locale, comunica l'intento che dovrebbe essere utilizzato solo entro func . Riduce anche i costi di manutenzione futuri dando a qualcuno che guarda alla classe meno che devono comprendere (a seconda di cosa stanno facendo).

Ci sono anche altre cose che puoi fare, come usare le variabili di chiusura.

void func2(int productId, string name)
{
   string formatMySpecialMessage(int errorCode, int reasonCode) = (errorCode, reasonCode) => {
    return $"An error ocurred while processing a request for item {productId}: {name}.  The error was error code {errorCode}, {reasonCode}";
};
    //lots of code with many error states that would use the formatMySpecialMessage function
}

Fare qualcosa come questo ti permette di riutilizzare una funzione e parte del contesto della tua funzione (l'ID prodotto e il nome in questo caso) senza dover passare quelle variabili in un'altra funzione per tutto il tempo.

Ci sono molti usi per loro. Se hai fatto sviluppo in Javascript probabilmente lo hai visto. Ho persino usato alcune funzioni locali come questa nel codice di produzione attuale.

Per tornare alla tua domanda originale, non c'è molta differenza tra i due esempi. Ma nessuno probabilmente dovrebbe fare manutenzione futura su un codice del genere. E quel codice è troppo semplicistico per giustificare veramente l'uso di una funzione locale.

    
risposta data 05.11.2018 - 21:27
fonte
0

La mia comprensione è che la differenza è puramente stilistica. Il compilatore genererà:

int M() 
{
    return LocalFunction();
} 

private static int LocalFunction() { return 0; }

Ora chiedi anche del vantaggio delle espressioni lambda, che è leggermente diverso.

Un'espressione lambda non richiede alcuna dichiarazione, quindi se abbiamo una funzione che viene utilizzata solo in un singolo posto, possiamo semplicemente scrivere la funzione in quel posto.

Forse il miglior esempio sono i predicati in Linq.

Dove prima dovevi definire una funzione separata per ogni ricerca o ordinamento che hai fatto su una raccolta, cioè

private int compare1(obj i, obj j) { ... }

List.Sort(compare1)

ora puoi farlo in linea

List.Sort(i,j  => ...);

Certo, è ancora stilistico e probabilmente meno performante. ma sicuramente è più ordinato.

    
risposta data 05.11.2018 - 22:30
fonte
0

Ci sono alcune differenze tra i metodi C # e lambda, quindi non è puramente stilistico. Un esempio è la creazione di chiusure. Raccomando Jon Skeets Article on Closures , ma il succo è che i lambda possono essere passati in giro come oggetti mentre sono ancora mantenere l'accesso alle variabili nel loro contesto originale. I metodi normali non possono!

    
risposta data 06.11.2018 - 01:07
fonte

Leggi altre domande sui tag