Domanda

Non riesco ancora a capire cosa sia una chiusura , quindi ho pubblicato questi due esempi e voglio sapere se questi esempi sono entrambi chiusure o no?

Esempio A:

List<DirectoryInfo> subFolders = new List<DirectoryInfo>();

Action<string> FilterSubFoldersStartA =
  s => subFolders.
       AddRange((new DirectoryInfo(s)).GetDirectories().
       Where(d => d.Name.StartsWith("A")));

FilterSubFoldersStartA(@"c:\tempa");
FilterSubFoldersStartA(@"c:\tempb");

Esempio B:

List<DirectoryInfo> subFolders = new List<DirectoryInfo>();

string filter = "A";

Action<string> FilterSubFoldersStartGen =
  s => subFolders.
       AddRange((new DirectoryInfo(s)).GetDirectories().
       Where(d => d.Name.StartsWith(filter)));

FilterSubFoldersStartGen(@"c:\tempa");

filter = "B"; 

FilterSubFoldersStartGen(@"c:\tempb");
È stato utile?

Soluzione

Sì, una chiusura non è altro che una funzione che "salva". alcune variabili dall'ambiente in cui è definito. Pertanto, in entrambi i tuoi esempi, l'azione definita salva l'elenco denominato sottocartelle , a cui può fare riferimento le funzioni anche dopo che la variabile locale non rientra nell'ambito. La variabile filter nel secondo esempio viene salvata anche dalla funzione definita.

Una definizione più precisa qui

Altri suggerimenti

Il tuo secondo esempio fa uso di chiusure (tecnicamente potresti dire che il compilatore calcola una chiusura in entrambi i casi, ma non la usi nel primo caso).

Una chiusura è semplicemente "tutte le variabili visibili a questa funzione". Niente di più, niente di meno. E ovviamente, in entrambi i casi, tali variabili esistono e sono determinate dal compilatore.

Ma cosa intendiamo di solito quando parliamo di " usando chiusure " è che le espressioni lambda possono utilizzare tutte le variabili locali visibili nel luogo in cui sono state dichiarate. Fanno tutti parte della sua chiusura.

Nel tuo caso, d è semplicemente il parametro della funzione lambda, e dato che questo è tutto ciò che usi nel primo caso, non stai davvero sfruttando le chiusure.

Nel secondo caso, filter non è definito nell'espressione lambda, non è un parametro o altro. È una variabile locale che è così visibile nel punto in cui viene dichiarata la lambda. Quindi fa parte della chiusura della lambda, che ti consente di fare riferimento nel corpo della lambda.

Modifica
Come sottolineato nei commenti, non ho letto il tuo codice troppo da vicino. Ho notato solo la seconda espressione lambda in ogni esempio. La prima lambda usa le chiusure (si chiude su sottocartelle in entrambi i casi.)

Entrambi gli esempi hanno chiusure. In "A" metodo anonimo acquisisce sottocartelle variabili locali. In "B" il metodo anonimo acquisisce le variabili locali sottocartelle e filtro. Dai anche un'occhiata qui .

P.S. Inoltre, tieni presente che stai effettivamente utilizzando la chiusura in " A " perché stai usando la variabile sottocartelle.

Ecco un esempio da http://www.agileatwork.com/a -proper-closing-in-csharp / di qualcosa che potrebbe sembrare un po 'più familiare se ti senti a tuo agio con JavaScript. Viene creata una chiusura attorno alla variabile tax , quindi il calcolo viene eseguito una sola volta. Non è esattamente facile per gli occhi, ma è bello poter fare questo tipo di cose in C #.

public class Order
{
    public Order(ITaxCalculator taxCalculator)
    {
        CalculateTax = new Func<Func<decimal>>(() =>
        {
            decimal? tax = null;
            return () =>
            {
                if (!tax.HasValue)
                {
                    tax = taxCalculator.Calculate(this);
                }
                return tax.Value;
            };
        })();
    }

    public Func<decimal> CalculateTax { get; set; }

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