la funzione aggregate esegue una serie di operazioni su una serie enumerata di parametri, man mano che scorre la lista data esegue l'operazione richiesta definendo il risultato e cosi via.
sostanzialmente nel tuo caso primario stai dicendo:
codice:
string output = Path.GetInvalidFileNameChars().Aggregate(fileName, (current, c) => current.Replace(c.ToString(), String.Empty));
dati tutta una serie di elementi: Path.GetInvalidFileNameChars()
partendo dal seme iniziale: fileName
trova il primo carattere dell'array (c - 0) e se trovato rimpiazza nella stringa corrente (current (inizialmente è il seme)) il valore definito e ridai il risultato interno
trova il secondo carattere dell'array (c - 1) e se trovato rimpiazza nella stringa corrente (current) il valore definito e ridai il risultato interno
cosi via per tutto l'array di char
giunto alla fine dell'array ti restituisce il risultato current attuale
Quindi fai questo
codice:
static string Aggregate(char[] chars, string replace = "", string seed = "")
{
string current = seed;
int count = chars.Length;
for (int i = 0; i < count; i++)
current = current.Replace(chars[i].ToString(), replace);
return current;
}
solitamente i conteggi, trovare minimi e massimi, lunghezze, etc.. esegue operazioni aggregate.
Nel secondo caso
codice:
Array.ForEach(Path.GetInvalidFileNameChars(), c => fileName = fileName.Replace(c.ToString(), String.Empty));
il risultato ottenuto è il medesimo, perché dici
per ogni elemento in Path.GetInvalidFileNameChars()
scorrendo il primo elemento (c - 0) nell'array, assegna a fileName il valore di fileName rimpiazzando per ogni corrispondenza di (c - 0), con il valore dato
scorrendo il secondo elemento (c - 1) nell'array, assegna a fileName il valore di fileName rimpiazzando per ogni corrispondenza di (c - 1), con il valore dato
cosi via per tutto l'array di char
Quindi fai questo
codice:
static void ForEach(char[] chars, ref string val, string replace = "")
{
int count = chars.Length;
for (int i = 0; i < count; i++)
val = val.Replace(chars[i].ToString(), replace);
}
oppure in modo equivalente con ritorno
codice:
static string ForEach(char[] chars, string val, string replace = "")
{
int count = chars.Length;
for (int i = 0; i < count; i++)
val = val.Replace(chars[i].ToString(), replace);
return val;
}
ottieni sempre il risultato che volevi, la differenza sta nei tempi, nel controllo e nel riutilizzo,
usare l'aggregate di Linq è quasi 3 volte più lento di usare il ForEach di Linq,
mentre usare un alternativa con for scritta da te è molto più performante di qualsiasi applicazione fornita da Linq,
questo semplicemente perchè in Linq vengono effettuati molti controlli sui dati e sulla loro gestione in caso di problematiche.
pertanto dipende tutto da cosa stai cercando di ottenere oltre il risultato nudo e crudo dell'operazione,
comunque nel tuo caso utilizzare aggregate è svantaggioso, usa ForEach.