HeaderBlog
LaConoscenza.NET
C# 3.0 introduce un modo alternativo per dichiarare le proprietà all´interno di una classe e di inizializzare gli oggetti in un modo molto più semplice ed immediato. Inizializzazione Oggetti
Visualizza l'intero eBook Introduzione a Linq  

Proprietà automatiche
C# 3.0 introduce un modo alternativo per dichiarare le proprietà all'interno di una classe. E’ una forma compatta che consente di evitare di dover dichiarare in modo esplicito il campo privato, reso accessibile tramite la property e di dover implementare gli operatori di accesso in scrittura e lettura get e set.
Prima della versione di C# 3.0 la dichiarazione di una property aveva la seguente forma:

        public classa Contact { 
      
          privatestring  _email; 
                public string Email {
                      get { return _email; }; 
                      set { _email= value; }; 
               }
         }

Ora, la medesima dichiarazione può essere fatta nella seguente nuova forma, molto più compatta e leggibile.

public classa Contact { 
     public string Email { get ; set ; }
}

Per dichiarare una property read only occorre far precedere l'operatore di accessibilità set con la parola riservata private.   

public string Email { get ; private  set ; }

Local Type Inference
Le variabili locali, tipizzate in modo implicito, sono un meccanismo che consente al compilatore di inferire il tipo della variabile locale in base all’espressione di inizializzazione. Il tipo della variabile viene dedotto dall'espressione usata per l'inizializzazione (type inference). Questo tipo di dichiarazione richiede l'uso della keyword var da inserire al posto del tipo della variabile da inizializzare.
La type inference può essere applicata sia alle variabili di tipo valore (tipi primitivi e strutture), sia alle variabili di tipo riferimento (classi). Affinchè possa essere ricavato il tipo, la dichiarazione deve obbligatoriamente comprendere un'espressione di inizializzazione, diversamente il compilatore non potrebbe inferire il tipo. Nel caso dei tipi di riferimento non è consentita l'inizializzazione con il valore null, in quanto occorre necessariamente instanziare la classe.

var i = 1;                             // Equivale a int i = 1;
var s = "Antonio";                // Equivale a string s = "Antonio";
var a = new int[] {1, 2, 3};     // Equivale a int[] a = …;
var c = new Contact();          // Equivale a Contact c = new Contact();

Qual è la principale utilità di questo tipo di dichiarazione?

Viene usata quando non è possibile visivamente individuare il tipo restituito ed occorre definire una variabile in grado di ospitare quel tipo, senza dover fare un cast, su un generico object, che richiederebbe successivamente un ulteriore operazione di cast per ottenere il valore. Inoltre viene usata nei casi in cui il valore è il risultato di una complessa espressione, in termini di definizione del tipo, come ad esempio nel caso dell’utilizzo delle Lambda Expression.

Array tipizzati implicitamente
La sintassi per creare array viene estesa con una nuova forma il cui tipo è ricavato mediante il type inference.

var Numeri = new[] { 1, 2, 3, 4, 5, 6, 7, 8, 9 };  // int[]
var Nomi = new[] { "Antonio", "Riccardo" };      // string[]

Array tipizzati implicitamente
Nell’ottica di ridurre il numero di parole nel codice, oltre alle proprietà automatiche è stato introdotto una sintassi più compatta per inizializzare oggetti e collezioni.
Nel caso di oggetti, l'inizializzazione utilizza la keyword new seguita dal nome del tipo e da un elenco di coppie proprietà/valore separate da una virgola e racchiuse in una coppia di parentesi graffe. Per esempio, per creare una istanza della classe Contact con l’inizializzazione di ciascuna delle sue proprietà:

var contact = new Contact {
      Id=1,  Nome = "Antonio", Cognome = "Samanton", 
      EmailAddress =
antonio@samanton.it
};

Questa forma è equivalente a quelle relativa all’invoca La forma sintattica appena vista è del tutto equivalente all'invocazione del costruttore di default di Contact, seguita dall'inizializzazione di ciascun membro della classe con il valore corrispondente. Nel caso di collezioni, (tipi che implementano l'interfaccia System.Collections.Generic.Icollection) è possibile effettuare l'inizializzazione degli elementi nel seguente modo:

var contacts = new Collection {
      new Contact {
            Id=1, Nome = "Antonio", Cognome = "Samanton", 
            EmailAddress =
antonio@samanton.it  
      },
      new Contact {
            Id=2, Nome = "Vittorio", Cognome = "Bassi", 
            EmailAddress =
vittorio@bassi.net  
      },
};

Object Initialization Expression
Si tratta di un meccanismo con cui è possibile all’interno della costruzione di un oggetto di inizializzarne i valori delle property e dei membri dichiarati pubblic oppure, nel caso di collection di inizializzarli con una lista di valori predefiniti. Supponiamo di dichiarare la seguente classe:

public classa Contact {
    public string Nome { get; set; }
    public string Cognome { get; set; }
    public int Età;
}

E di inizializzare la classe nel modo usuale:

Contact impiegato = new Contact();
impiegato.Nome = "Antonio";
impiegato.Cognome = "Samanton";

Con l’Object Initialization Expression è possibile inserire l’inizializzazione sulla stessa riga in cui viene instanziato l’oggetto:

Contact impiegato = new Contact { Nome="Antonio", Cognome="Samanton" };          

in questa nuova forma di sintassi viene utilizzato il costruttore di default della classe e vengono assegnati i valori alle proprietà o ai membri della classe dichiarati pubblici.

Questo tipo di inizializzazione può essere utilizzata anche con gli array. Ad esempio è possibile creare una lista di collection di interi ed usare lo stesso tipo di inizializzazione.

List<int> numeri = new List<int> { 1, 3, 5, 45 };

La medesima sintassi può essere applicare anche ad una lista di Contact e quindi combinare i due tipi di inizializzazioni:

List<Contact> listContact= new List<Contact> {
      new Contact {Nome="Antonio", Cognome="Samanton" },
      new Contact {Nome="Francy", Cognome="Samanton" }
};

         string s = listContact[0].Cognome;

Il grosso vantaggio di questo tipo di sintassi è che il tutto, è considerato dal compilatore, come una unica istruzione e quindi può essere utilizzata in tutti i contesti in cui è necessario avere un’unica istruzione, per esempio nelle lambda Expression, ecc.
 
 

Data Inserimento Post 05/02/2009 12.41.46  |  Social Bookmark
  • Digg
  • del.icio.us
  • Google
  • Yahoo
  • Technorati
  • Facebook
  • OKNOtizie
  • Email
 
L´Anonymous type consente di incapsulare, un gruppo di proprietà di solo lettura, in un oggetto, senza dover prima definire il tipo, in quanto dedotto in automatico dal compilatore. Questo tipo non è disponibile a livello di codice sorgente e non è consentito utilizzarlo per definire gli altri tipi della classe (metodi e eventi)Anonymous type
Visualizza l'intero eBook Introduzione a Linq  

L'Anonymous type è un tipo di riferimento che deriva direttamente dalla classe System.Object. Consente di incapsulare, un gruppo di proprietà di solo lettura, in un oggetto, senza dover prima definire il tipo, in quanto dedotto in automatico dal compilatore. 
Questo tipo non è disponibile a livello di codice sorgente e non è consentito utilizzarlo per definire gli altri tipi della classe (metodi e eventi). Inoltre non è possibile eseguire il cast a un tipo diverso da object (per esempio ad una interfaccia).
La sintassi è caratterizzata dalla dichiarazione di una serie di proprietà, il cui tipo è ricavato mediante la
type inference, cioè in base all'espressione di inizializzazione:

         var point = new { X=1, Y=2, Z=3 };

L'anonymous type è generalmente utilizzato nella clausola select di una espressione di query, al fine di ottenere un sottoinsieme delle proprietà degli  elementi contenuti nella sequenza di origine:

var queryProdotti = 
      f
rom prd in prodotti 
      where prd.Prezzo > 100.00 
      select new { prd.Colore, prd.Prezzo };

foreach (var p in queryProdotti ) {
      Console.WriteLine("Colore={0}, Prezzo={1}", p.Colore, p.Prezzo);
}

L'anonymous type utilizza i nomi dell'elemento di origine. Per assegnare nomi nuovi alle proprietà, occorre modificare la select come segue:

                  select new { a= prd.Colore, b= prd.Prezzo };

Lo scopo di un tipo anonimo è il metodo in cui è definito. Per passare un tipo anonimo o un insieme che contiene tipi anonimi, al di fuori del limite del metodo, occorre eseguire prima il cast del tipo sull'oggetto. Tuttavia in questi casi è più opportuno considerare l’uso di una normale struttura o una classe denominata.
In altri termini è opportuno utilizzare un tipo anonimo in un'espressione di query quando si verificano entrambe le seguenti condizioni:

  • Si desidera restituire solo alcune delle proprietà di ogni elemento di origine
  • Non occorre archiviare la query all'esterno del metodo in cui è eseguita la query.

Delegate
I delegate incapsulano un riferimento ad un metodo, cioè consentono di fornire ad un’applicazione la possibilità di registrare un metodo (funzione di CallBack) in un componente. Il metodo sarà invocato quando si verificherà l’evento a cui è associato.

classa Program { 
      delegate void DisplayMsg(string s); // Prototipo del Metodo

      static void DisplayString(string k) 
      { 
            System.Console.WriteLine(k); 
      } 
      static void Main(string[] args) 
      { 
            DisplayMsg Pf = new DisplayMsg(Program.DisplayString); 
            Pf("Attivazione del metodo DisplayString"); 
      }
}

Anonymous Methods
I metodi anonimi sono simili ai delegate, ma richiedono meno codice, non hanno un identificatore e non sono dichiarati come i normali metodi, in quanto vengono connessi direttamente agli eventi:

Button btnHello = newButton();
btnHello.Click += delegate { MessageBox.Show("Hello"); };

Il metodo è anonimo perché usa la keyword delegate seguita dal corpo del metodo delimitato dalle parentesi graf. Il metodo anonimo deve terminare con il il punto e virgola. Per meglio comprendere le differenze rispetto al semplice uso dei delegate, consideriamo il seguente esempio:

classa Program { 
      delegate void DisplayMsg(string s); // Crea un’istanza del delagate
       //-------------------------------------------- Instanzia il delagate con il metodo anonimo
       DisplayMsg DisplayString = delegate(string j) { System.Console.WriteLine(k); } 

       static void Main(string[] args) 
       { 
               DisplayString("Il Delegate usa l'anonymous method.");
        }
}

 

Data Inserimento Post 05/02/2009 22.13.55  |  Social Bookmark
  • Digg
  • del.icio.us
  • Google
  • Yahoo
  • Technorati
  • Facebook
  • OKNOtizie
  • Email
 
Lambda Expression
Visualizza l'intero eBook Introduzione a Linq  

Le lambda expression consentono di semplificare la sintassi dei metodi anonimi, una sintassi molto utilizzata nelle query expression in Linq nei due seguenti casi:

  • per specificare i predicati nelle condizioni dei filtri.
  • per fare la proiezione dei risultati di una select, cioè prendere i dati da una struttura per proiettarli in un’altra, con un formato differente.

 La lambda expression è un modo per creare funzioni on-line. Si compone di tre parti:

  • un elenco di parametri compresi in una coppia di parentesi tonde (sono facoltative se il parametro è uno solo), per i quali può essere o meno indicato il tipo corrispondente.
  • l'operatore =>;
  • una espressione, un'istruzione o un blocco di codice, che usa i parametri e che fornisce un valore di ritorno.

La lambda expression deve essere all’interno di un’assegnazione o di una chiamata ad una funzione. Per meglio comprendere, consideriamo il seguente esempio:

      delegate int funz (int a, int b);           // prototipo necessario per dichiarare i tipi
      funz f = delegate (int a, int b) { return a+b; } ;  // assegna ad f, di tipo funz e il codice
      int  j =  f (5, 6);
                // esegue la somma fra 5 e 6

      delegate (int a, int b) { return a+b; }  questa espressione puo essere semplificata
      (int a, int b) => { return a+b; }     la keyword delegate  può essere sostituita da =>
      (a, b) => { return a+b; }   è possibile rimuovere i tipi, il compilatore li ricava dal contesto

Fra le parentesi graf è possibile avere qualsiasi numero di istruzioni, ma se vi è solo un return è possibile effettuare la seguente ulteriore semplificazione formale:

         (a, b) => a + b    // il punto e virgola non ci vuole perché è una semplice espressione

L’espressione Lambada inizia con la definizione delle variabili passate al delegate (dichiarate a sinistra dell’operatore =>), mentre a destra viene definita la logica elaborata per ogni elemento o l’operazione che si vuole eseguire.

int[] nums = { 1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024 };
int singleNum = nums.Single(x => (x > 16  &&  x < 64));

Nel precedente esempio è stato utilizzato, nell’elaborazione, un operatore di query, detta anche proprietà di esplorazione, applicato ad un array di integer. Quindi per molti aspetti le lambda expression sono equivalenti agli anonymous methods, ma consentono definizioni più compatte e funzionali. La loro principale utilità consiste nella possibilità di passare come parametro a un metodo, il nome di una funzione.

Data Inserimento Post 20/01/2009 23.38.43  |  Social Bookmark
  • Digg
  • del.icio.us
  • Google
  • Yahoo
  • Technorati
  • Facebook
  • OKNOtizie
  • Email
 
Extension Methods
Visualizza l'intero eBook Introduzione a Linq  

Extension Methods
Gli extension methods sono metodi statici. Costituiscono un meccanismo mediante il quale si può concettualmente estendere una classe senza derivarla in una nuova classe, attraverso il meccanismo dell'ereditarietà. In realtà l’estensione è solo apparente, in quanto sono un surrogato sintattico che consente di ottenere dei costrutti più intuitivi e più facilmente leggibili.

Per dichiarare un extension method occorre modificare la firma del metodo statico, facendo precedere al primo parametro,  la parola chiave this. Il tipo del primo parametro rappresenta la classe che viene estesa: il metodo statico diventa parte integrante dell'interfaccia e può essere invocato come un normale metodo di istanza.

static classa ExtMethods { 
      
public static int Raddoppia(this int d) 
      

               
return d + d; 
      } 
      
public static int Incrementa(this int d) 
      { 
               return ++d; 
      }
}

         int y = ExtMethods.Raddoppia(ExtMethods.Incrementa(x)); 

         questo formalismo può essere espresso mediante una forma più compatta:

         y = x.Incrementa().Raddoppia();

Partial Methods
I Partial Methods aggiungono la possibilità di definire metodi vuoti che possono essere implementati o meno nelle partial classa. Il fine è di poter separare in sorgenti diversi la definizione dei metodi e la loro implementazione. In genere vengono utilizzati dai generatori di codice, per consentire una più efficace personalizzazione. Sono disponibili due diverse sintassi

  • Defining declaration, per consentire la chiamata
  • Implementing declaration, per implementare effettivamente la chiamata

partial void Funz01()

         Console.WriteLine("Funzione 1");
}

partial void Funz01();
partial void Funz02();

Data Inserimento Post 21/01/2009 3.17.30  |  Social Bookmark
  • Digg
  • del.icio.us
  • Google
  • Yahoo
  • Technorati
  • Facebook
  • OKNOtizie
  • Email
 
Query Expression
Visualizza l'intero eBook Introduzione a Linq  

La sintassi legata alle query Expression esiste unicamente in funzione di Linq. Il fine è di fornire un aspetto formale simile a SQL. In realtà al suo interno invoca gli adeguati extension methods.

La Query Expression è semplicemente un aiuto sintattico che riguarda solo una parte degli extension methods esistenti, per cui quando ad una funzionalità non corrisponde una keyword nella query expression, occorre usare (anche in modo misto) gli extension methods.

La Query Expression è un costrutto sintattico che può essere meglio compresa, riferendosi alla sintassi di Linq. Tuttavia è importante innanzitutto comprendere l’intima logica di funzionamento. Consideriamo il seguente esempio che non fa uso delle query Expression:


                        // Definizione dell'oggetto Persone 
                        varPersone = new[] {

                 new { Nome="Antonio", Budget= 2000.00 },

                 new { Nome="Francy", Budget= 3000.00 },

                 new { Nome="Maria", Budget= 4000.00 }

            };

 

            // Definizione della query per l'estrazione dei dati
            
var query = Persone

                .Where(p=> p.Budget > 2000.00)

                .OrderBy(p => p.Budget)

                .Select(p=> new { p.Nome, PercBudget = p.Budget / 100 });

 

            // Esecuzione query ed estrazione dei dati

            foreach (var result in query) {

                string s= result.Nome;

                Console.WriteLine(result);

            }

Da questo esempio si rileva: una query in Linq è costruita utilizzando alcune delle funzionalità di C# 3.0, per esempio la lambda espression

           .Where(p=> p.Budget > 2000.00)

 

gli Extension Method, per esempio .Where consentono di estendere la classe a cui Persone appartiene, che nell’esempio è un array di tipi anonimi.

Questa definizione è usata per creare con var query un oggetto che estrae dall’array Persone

·         gli elementi che hanno un budget > di 2000.00,

·         ordinati per budget

·         da cui vengono estratti i campi Nome e la percentuale del Budget

L’esempio che segue riscrive il codice precedente utilizzando le Query Expression. Il risultato è il medesimo, ma il codice appare essere decisamente più intuitivo:

        var query = from p in Persone
                         where p.Budget > 2000.00
                         orderby p.Budget
                         selectnew { p.Nome, Perc = p.Budget/100 };

 

            foreach (var result in query)

       Console.WriteLine(result);

 

La lettura della query expressione è la seguente: consideriamo l’elemento Persone che è parte di una iterazione definita da from che dice: per ogni oggetto in Persone considera l’identificatore p, filtra con p.Budget maggiore di 2000.00, ordina in base a p.Budget e seleziona gli elementi con il tipo anonimo che segue il costrutto select new.
Anche se è possibile scrivere il tipo, l’utilizzo di var consente di semplificare la scrittura del codice.

 

Supponiamo di voler estrarre una serie di valori di budget, da cui si desidera ricavare il valore di budget max. In questo caso si può applicare al risultato della query l'operatore max() 

 

            Ienumerable<double> qMaxBudget =

                from p1 in Persone

                select p1.Budget;

            var max = qMaxBudget.Max();

 

Una ulteriore sequenza di esempi, possono evidenziare come l'uso di questi nuovi nuovi costrutti, possono semplificare ed aumentare la leggibilità del codice. Consideriamo due liste su cui si desidera eseguire alcune operazioni:
 

    List <int> Num1 = new List<int>() {5,4,1,3,9,8,6,7,2,0};
    List<int> Num2 = new List<int>() {1,14,11,13,19,18,16,17};

      

       Ienumerable<int> filteringQuery =

            from num in Num1

            where num < 3 || num > 7

            select num;

       il tipo Ienumerable<int> può essere var 

 

       var orderingQuery =

                from num in Num1

                where num < 3 || num > 7

                orderby num ascending

                select num;

     

Igrouping è una collezione di oggetti che hanno in comune una key.

 

  string[] groupingQuery = { "auto", "bici", "carro", "bus"};

  Ienumerable<Igrouping<char, string>> queryFoodGroups =

           from item in groupingQuery

           group item by item[0];

     

double average = numbers1.Average();

Enumerable<int> concatenationQuery = Num1.Concat(Num2); 
Ienumerable<int> largeNumbersQuery = Num2.Where(c => c > 15);


  int numCount1 = (from num in numbers1

                 where num < 3 || num > 7

                 select num).Count();

 

Data Inserimento Post 21/01/2009 3.17.51  |  Social Bookmark
  • Digg
  • del.icio.us
  • Google
  • Yahoo
  • Technorati
  • Facebook
  • OKNOtizie
  • Email
 
Gli Operatori in Linq
Visualizza l'intero eBook Introduzione a Linq  

Linq utilizza una sintassi fortemente tipizzata ed elabora in modo efficace le query standard mediante una serie di operatori che agiscono sulle sequenze e sulle funzioni di aggregazione. L’efficacia di questi operatori è principalmente dovuta alle Lambda Expression 

Il nucleo delle potenzialità di LINQ deriva dalla sintassi query fortemente tipizzata, ma diventa ancora più efficace quando viene usato insieme con uno o più operatori di query standard. Questi operatori sono definiti nello spazio dei nomi System.Linq come metodi di estensione sulle classi statiche  Enumerable e Queryable, cioè possono essere utilizzati sugli oggetti che implementano IEnumerable<T>  o IQueryable<T>.

Diversi operatori, durante l'esecuzione di query che eleborano singoli elementi, utilizzano i delegati e quindi le espressioni Lambda, cioè forme abbreviate di un delegate anonimo.

   int[] nums = { 1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024 };

Supponiamo di utilizzare l’operatore Single su una matrice di interi, per estrarre un valore che soddisfa la condizione specificata in una espressione lambda:

int singleNum = nums.Single(x => x > 16 && x < 64);

Sono disponibili diversi tipi di operatori (rilevabili all'interno delle classi Enumerable e Queryable). La tabella che segue rappresenta una sintesi delle loro funzionalità.

 Operatore

 Descrizione

  Aggregazione

 

 Aggregate

Esegue un metodo personalizzato su una sequenza

 Average

Calcola la media di una sequenza di valori numerici

 Count

Restituisce il numero di elementi in una sequenza come un valore int

 LongCount

Restituisce il numero di elementi in una sequenza come un valore long

 Min

Trova il numero minimo in una sequenza di numeri

 Max

Trova il numero massimo in una sequenza di numeri

 Sum

Somma i numeri in una sequenza

 Concatenazione

 

 Concat

Concatena due sequenze in una sequenza

 Conversione

 

 Cast

Converte gli elementi di una sequenza in un tipo dato

 OfType

Filtra gli elementi di una sequenza di un tipo dato

 ToArray

Restituisce una matrice da una sequenza

 ToDictionary

Restituisce un dizionario da una sequenza

 ToList

Restituisce un elenco da una sequenza

 ToLookup

Restituisce una ricerca da una sequenza

 ToSequence

Restituisce una sequenza IEnumerable

 Elemento

 

 DefaultIfEmpty

Crea un elemento predefinito per una sequenza vuota

 ElementAt

Restituisce l'elemento a un determinato indice in una sequenza

 ElementAtOrDefault

Restituisce l'elemento a un determinato indice in una sequenza o un valore predefinito se l'indice è fuori intervallo

 First

Restituisce il primo elemento di una sequenza

 FirstOrDefault

Restituisce il primo elemento di una sequenza o un valore predefinito se non viene rilevato alcun elemento

 Last

Restituisce l'ultimo elemento di una sequenza

 LastOrDefault

Restituisce l'ultimo elemento di una sequenza o un valore predefinito se non viene rilevato alcun elemento

 Single

Restituisce il singolo elemento di una sequenza

 SingleOrDefault

Restituisce il singolo elemento di una sequenza o un valore predefinito se non viene rilevato alcun elemento

  Uguaglianza

 

 SequenceEqual

Confronta due sequenze per verificare se sono equivalenti

 Generazione

 

 Empty

Genera una sequenza vuota

 Range

Genera una sequenza da un intervallo

 Repeat

Genera una sequenza ripetendo un elemento per un determinato numero di volte

 Raggruppamento

 

 GroupBy

Raggruppa gli elementi di una sequenza in base a un determinato criterio di raggruppamento

 Unione

 

 GroupJoin

Esegue un'unione raggruppata di due sequenze

 Join

Esegue un'unione interna di due sequenze

 Ordinamento

 

 OrderBy

Ordina una sequenza in base ai valori in ordine crescente

 OrderByDescending

Ordina una sequenza in base ai valori in ordine decrescente

 ThenBy

Ordina una sequenza già ordinata in ordine crescente

 ThenByDescending

Ordina una sequenza già ordinata in ordine decrescente

 Reverse

Inverte l'ordine degli elementi di una sequenza

  Partizionamento

 

 Skip

Restituisce una sequenza senza un determinato numero di elementi

 SkipWhile

Restituisce una sequenza senza gli elementi che non soddisfano un'espressione

 Take

Restituisce una sequenza con un determinato numero di elementi

 TakeWhile

Restituisce una sequenza con gli elementi che soddisfano un'espressione

  Proiezione

 

 Select

 Crea una proiezione di parti di una sequenza

 SelectMany

 Crea una proiezione di tipo uno a molti delle parti di una sequenza

 Quantificatori

 

 All

 Determina se tutti gli elementi di una sequenza soddisfano una condizione 

 Any

 Determina se degli elementi di una sequenza soddisfano una condizione

 Contains

 Determina se una sequenza contiene un determinato elemento

 Restrizione

 

 Where

 Filtra gli elementi di una sequenza

 Serie

 

 Distinct

 Restituisce una sequenza senza elementi duplicati

 Except

 Restituisce una sequenza che rappresenta la differenza tra due sequenze

 Intersect

 Restituisce una sequenza che rappresenta l'intersezione tra due sequenze

 Union

 Restituisce una sequenza che rappresenta l'unione tra due sequenze

Data Inserimento Post 21/01/2009 17.30.17  |  Social Bookmark
  • Digg
  • del.icio.us
  • Google
  • Yahoo
  • Technorati
  • Facebook
  • OKNOtizie
  • Email