Linq in C#

di
Anonimizzato10204
il
18 risposte

Linq in C#

Salve a tutti sto guardando il LINQ e qualcosa riesco a fare modificando gli esempi, solo che non capisco quello che scrivo! Ad esempio
var result = ordini.Where(o => o.Id == 1);
Ho capito che seleziona tutti gli id uguali a 1, ma cosa è Where? La classe List<Ordini> non ha un metodo Where, e la freccia cosa è?

18 Risposte

  • Re: Linq in C#

    Ciao

    Where altro non è che il metodo che permette l'esecuzione di un filtro su un oggetto, in questo caso lista. E' l'equivalente del Where in SQL. Per capire meglio ti conviene, invece che cambiare gli esempi che non capirai mai nulla, studiati la documentazione

  • Re: Linq in C#

    Studiare la documentazione è senz' altro un buon consiglio!

    Mi sembra che tu abbia delle perplessità sulla sintassi (vedi domanda sul Where).
    Intanto bisogna cominciare a dire che per il LINQ esistono due sintassi:

    La prima è quella nativa basata su caratteristiche del linguaggio:
    var result = ordini.Where(o => o.Id == 1);
    la seconda è più simile alle query SQL, non sembra C#, e si chiama Query Syntax:
    var result = from o in ordini where o.Id == 1 select o;
    Tieni presente che quando il compilatore incontra la seconda la converte nella prima. L' uso della seconda forma ha delle limitazioni.

    Ora veniamo alla tua domanda 'da dove salta fuori Where?' È vero che la classe List NON ha il metodo Where, ma quando fai, using System.Linq, ti porti dentro una serie di 'Extension Methods' che aggiungono nuovi metodi alla classe List.

    Per quanto riguarda la domanda 'cosa è la freccia', la risposta è, si tratta dell' operatore di una 'Lambda Expression' (nome inquietante ) , si tratta di una sintassi particolare per descrivere un metodo anonimo (che poi è un delegato).

    Quindi riassumendo, in 'ordini.Where(o => 0.Id == 1)', Where è un extension method che vuole come parametro un delegato, in pratica la Where richiamerà il delegato per valutare la condizione. Una roba del genere:
    
    bool MyCondition(Ordine o)
    {
       return o.Id == 1;
    }
    
    var result = ordini.Where(MyCondition);
    
    Nota che questo esempio è corretto e si compila, è la stessa cosa del tuo esempio senza la lambda expression.
  • Re: Linq in C#

    Grazie fonzarelli, il consiglio è buono. Grazie barba59, l'ultimo esempio è illuminante!
    Ancora una cosa, ma gli extension method li posso scrivere pure io?
  • Re: Linq in C#

    Orso Bruno ha scritto:


    Ancora una cosa, ma gli extension method li posso scrivere pure io?
    Aggiungere un extention method è semplicissimo (forse un pò troppo). Per esempio se vuoi aggiungere un nuovo metodo alla classe stringa devi scrivere in una qualsiasi classe statica una cosa del genere:
    
       public static string AggiungiAgliEstremi(this string s, char ch)
       {
           return ch + s + ch;
       }
    
    Nota l' uso di 'this'.
    A questo punto tutte le stringhe avranno il metodo 'AggiungiAgliEstremi':
    
       string s = "aaa";
       string z = s.AggiungiAgliEstremi('_');
       // z ora vale "_aaa_"
    
    Il funzionamento del LINQ si basa in gran parte su questo. Includendo System.Linq vengono aggiunti gli estension method 'Where', 'Select' ecc. alle classi contenitore.
  • Re: Linq in C#

    Scusa ma non capisco, ma nella query ordini.Where(o => o.Id == 1); il tipo di 'o' quale è?
    Per le estensioni invece è tutto chiaro.
  • Re: Linq in C#

    Il tipo 'o' si riferisce all'oggetto su cui applichi il metodo (ordini nel tuo caso). Come ha spiegato anche barba59, Where è un extended method. Il primo parametro di tali metodi è, se vedi ad esempio l'esempio sempre di barba59
    this String s
    questo indica che il primo parametro equivale alla stringa su cui viene applicato il metodo, ecco perchè nell'esempio nell'utilizzo del metodo non viene passato il primo parametro
    s.AggiungiAgliEstremi('_')
    Nel caso di Where la dichiarazione, da documentazione msdn, è
    public static IEnumerable<TSource> Where<TSource>(
    	this IEnumerable<TSource> source,
    	Func<TSource, bool> predicate
    )
    quindi 'o' altro non è che la sorgente dati su cui viene applicato il metodo
  • Re: Linq in C#

    @ fonzarelli, thread interessante! in effetti cercando di rispondere ho approfondito cose che non mi sarei mai sognato di guardare e mi sto chiarendo le idee su diversi punti

    Quando vengono compilate le query LINQ, e più in generale le lambda-expression, il compilatore applica delle 'regole di inferenza' per determinare il tipo delle variabili, ad esempio nella query:
    
    var result = ordini.Where(o => o.Id == 1);
    
    Supponendo che ordini sia di tipo List<Ordine>, il compilatore inferisce che 'o' sia di tipo 'Ordine' (e quindi ha un campo Id), cioè usa il tipo dell' oggetto contenuto nella lista da cui parte la query.

    È un pò come se il foreach ti permettesse di non scrivere il tipo delle variabile di iterazione perchè lo può dedurre dal tipo su cui itera (questo non lo fà, è solo un esempio).

    In quest' altro caso:
    
    delegate int MyDelegate(string text);
    
    MyDelegate p = s => s.Length * 2;
    
    int n = p("ciao");   // restituisce 8
    
    Pure qui non c' è scritto da nessuna parte il tipo di s (eppure accetta s.Length), anche in questo caso viene applicata una regola di inferenza, visto che il risultato della lambda expression viene assegato a un delegato che vuole una stringa, deduce che s sia di tipo string.

    In pratica la lambda expression è come se fosse una chiamata a funzione, a sinistra della freccia => c' è il parametro e a destra il corpo della funzione, il tipo del parametro viene dedotto dal contesto.

    In realtà se uno vuole il tipo lo può scrivere, ad esempio:
    
    MyDelegate p = (string s) => s.Length * 2;
    
    Scritto in questo modo assomiglia di più ad una chiamata a funzione.
  • Re: Linq in C#

    Barba, Hai ragiono. Linq è un mondo vasto che nemmeno io immaginavo fosse così potente, anche perchè l'ho usato gran poco Infatti per rispondere faccio quello che dovrebbero fare tutti i buoni programmatori, mi documento nella documentazione ufficiale, approfondendo poi. Un pò quello che fai te

    Pensa che subito consideravo Linq soltanto ad un sostituto si Sql in modo da rendere per l'ennesima volta ancora più semplice la programmazione, aprendo ancora di più le porte ai non programmatori. Invece si sta rilevando un ottimo strumento anche per noi programmatori più esperti per evitarci la scrittura di cicli su cicli Infatti sto pensando di iniziare a sostituire, dove si puoi, tutti quei cicli foreach sparsi per il mio codice ed approfondire sempre di più lo strumento
  • Re: Linq in C#

    Pure io all' inizio avevo sottovalutato il Linq e non ne avevo capito l' importanza.

    fonzarelli ha scritto:


    Invece si sta rilevando un ottimo strumento anche per noi programmatori più esperti per evitarci la scrittura di cicli su cicli Infatti sto pensando di iniziare a sostituire, dove si puoi, tutti quei cicli foreach sparsi per il mio codice ed approfondire sempre di più lo strumento
    Non parlarmene! se penso a tutto il tempo passato a scrivere cicli su cicli che facevano sempre le stesse cose
    Chissà quante volte è stato scritto un ciclo che somma degli elementi se soddisfano una condizione, ad es:
    
    int tot = 0;
    foreach (Ordine o in ordini)
    {
        if (o.a == 1)
            tot += o.b;
    }
    
    in Linq:
    
    int tot = ordini.Where(o => o.a == 1).Sum(o => o.b);
    
    Una curiosità, per quanto riguarda le due sintassi (quella nativa e la query syntax), tu quale preferisci/consigli?
  • Re: Linq in C#

    Non parlarmene! se penso a tutto il tempo passato a scrivere cicli su cicli che facevano sempre le stesse cose
    Chissà quante volte è stato scritto un ciclo che somma degli elementi se soddisfano una condizione
    Quotidianamente!! almeno per quanto mi riguarda
    Una curiosità, per quanto riguarda le due sintassi (quella nativa e la query syntax), tu quale preferisci/consigli?
    scusa, non riesco ad afferrare la tua domanda
  • Re: Linq in C#

    fonzarelli ha scritto:


    Una curiosità, per quanto riguarda le due sintassi (quella nativa e la query syntax), tu quale preferisci/consigli?
    scusa, non riesco ad afferrare la tua domanda
    Mi riferivo ai due possibili modi di scrivere le query:

    La prima forma è quella nativa (non so se il nome è quello corretto):
    var result = ordini.Where(o => o.Id == 1);
    la seconda è più simile alle query SQL, e si chiama Query Syntax:
    var result = from o in ordini where o.Id == 1 select o;
    Le due query fanno la stessa cosa, anzi da quello che so, la seconda viene trasformata nella prima dal compilatore.
  • Re: Linq in C#

    Ok, ora ho capito

    oddio, la prima notazione è più orientata ad oggetti, la seconda ricorda molto sql, quindi forse più adatto ai nuovi programmatori Linq. Francamente non ho preferenze, ora come ora... sarebbe da controllare cosa conviene di più a livello prestazionale e di utilizzo.
  • Re: Linq in C#

    Ma è stupendo!!! Ho sempre sofferto ogni volta che dovevo ordinare un array rispetto a un campo di un oggetto,qui è facilissimo!
    var v = ordini.OrderBy(o => o.a)
  • Re: Linq in C#

    Per non parlare del doppio ordinamento. Ti sarà capitato di dover ordinare rispetto a due campi, uno principale e l'altro secondario, in linq scrivi:
    var result = ordini.OrderBy(o => o.a).ThenBy(o => o.b)
    Oppure le liste nelle liste, pensa a un elenco di ordini, ogni ordine contiene un elenco di acquisti e per ogni acquisto hai peso e prezzo. Per calcolare la spesa totale hai bisogno di un doppio ciclo, sugli ordini e sugli acquisti, invece in linq scrivi:
    var tot = ordini.Sum(o => o.Acquisti.Sum(a => a.Peso * a.Prezzo))
Devi accedere o registrarti per scrivere nel forum
18 risposte