In alcune situazioni vorremmo poter estendere classi esistenti nel framework o il altre dll oppure potrebbe essere necessario estendere ad esempio le classi autogenerate ad esempio da Linq to Sql. Per farlo abbiamo a disposizione due diverse strade (oltre all'ereditarietà).

Se una classe è dichiarata con la keywork "partial" è possibile estenderla aggiungendo metodi e proprietà. Per farlo basta dichiarare in un altro file (se stiamo lavorando con Linq to Sql ovviamente non vogliamo modificare le classi autogenerate!) una classe con lo stesso nome di quella che vogliamo modificare e la keyword partial. In questo modo possiamo aggiungere tutto quello di cui abbiamo bisogno alla classe.
public partial class vIndividualCustomer
    {
        public string DammiInfo()
        {
            return (this.Title + " " + this.FirstName + " " + this.MiddleName
                    + " " + this.LastName).ToUpper();
        }
    }
Nell'esempio abbiamo aggiunto un semplice metodo alla classe generata dalla vista vIndividualCustomer con Linq to Sql utilizzando il db AdventureWorks. Tutte le classi generate da Linq to Sql hanno il modificatore partial per poter permettere questo tipo di operazioni.
Un altro modo per estendere una classe è usare gli extension methods, in questo caso possiamo aggiungere solo dei metodi ma possiamo farlo per qualunque classe accessibile dal nostro codice. Per farlo abbiamo bisogno di una classe statica in cui inserire i nostri metodi. Lo "stesso" metodo definito nella classe parziale può essere definito nel seguente modo:
public static class extension
    {
        public static string DammiInfoExtension(this vIndividualCustomer vic)
        {
            return (vic.Title + " " + vic.FirstName + " " 
                  + vic.MiddleName + " " + vic.LastName).ToUpper();
        }
    }

 

Il modificatore "this" dell'argomento del metodo indica la classe che vogliamo estendere. Per curiosità abbiamo scritto un semplicissimo benchmark per misurare eventuali differenze nella velocità di esecuzione:
using (var dc = new dcDataContext())
{
    var vics = dc.vIndividualCustomers.ToList();

    long infoDurata = 0;
    long infoDurataExt = 0;

    Stopwatch sw = new Stopwatch();
    for (int i = 0; i < 1000; i++)
    {
        sw.Reset();
        sw.Start();
        foreach (var item in vics)
        {
            item.DammiInfo();
        }
        sw.Stop();

        infoDurata += sw.ElapsedMilliseconds;

        sw.Reset();
        sw.Start();
        foreach (var item in vics)
        {
            item.DammiInfoExtension();
        }
        sw.Stop();

        infoDurataExt += sw.ElapsedMilliseconds;
    }

}

 

Il nostro codice non evidenzia grosse differenze nella velocità di esecuzione. Tuttavia test di questo genere non sono sicuramente risolutivi e sicuramente la decisione di utilizzare una strada o l'altra (quando possibile) dipendono da diversi fattori, non ultima la leggibilità del codice fattore determinante all'interno di un team di sviluppo.
comments powered by Disqus