Type Inference

Una caratteristica molto interessante del framework è l'inferenza dei tipi, cioè la capacità del compilatore di capire quali sono i tipi da usare senza che il programmatore li dichiari esplicitamente. Questa caratteristica è stata notevolmente utilizzata nel framework 3.0, ma è presente anche nel 2.0.

Ad esempio:

class FooClass

{

public void Test() {    

Foo<int, string>(10, "aaa");

Foo(10, "aaa");

Foo("bbb", 10);

}

 

void Foo<I, J>(I parA, J parB) {

Console.WriteLine("First method");

}

}

Nel metodo Test, le chiamate al metodo Foo sono tutte lecite. Nel primo caso vengono esplicitati i parametri di tipo, nel secondo il compilatore "conclude" che i tipi I e J sono rispettivamente int e string, mentre nel terzo caso I e J sono rispettivamente string e int. L'inferenza dei tipi rende meno prolisso il codice ma nasconde delle insidie.

Come più volte ha dimostrato Adrian nei suoi post, quando si lascia al compilatore l'interpretazione del nostro codice, non sempre le scelte intraprese sono quelle che noi ci aspetteremo. Ad esempio:

class FooClass

{

public void Test() {

Foo<int, string>(10, "aaa");

Foo(10, "aaa");

}

 

void Foo<I, J>(I parA, J parB) {

Console.WriteLine("First method");

}

 

void Foo<I, J>(int parA, string parB){

Console.WriteLine("Second method");

}

}

In questo caso l'output generato chiamando il metodo Test sarà:

First method

Second method

Quindi quando specifichiamo i parametri di tipo int e string il compilatore sceglie il primo dei due metodi, anche se a qualcuno sembrerebbe più logico il secondo. Se non specifichiamo i parametri di tipo, il compilatore sceglie il secondo dei metodi.

Cose da non fare mai

L'articolo è un pò vecchiotto, ma fa riflettere visto che siamo all'alba di così tante nuove tecnologie:

http://italian.joelonsoftware.com/Articles/ThingsYouShouldNeverDoPar.html

Ancora su WPF

Prendo spunto dai post di Gabriele e Raffaele. Secondo me non dobbiamo pensare che WPF debba stravolgere quanto fatto da WinForms. Non dovremo per forza riprogettare tutta l'interfaccia dei nostri applicativi. La maggior parte delle applicazioni va bene così. In effetti anche Vista ha applicazioni alla Xp con i controlli standard con grafica migliorata. Quindi già il porting delle applicazioni "ASIS" miglioreranno la User Experience sotto Vista. Il vero vantaggio di WPF sta invece nel fatto che da oggi si possono scrivere applicazioni che prima era molto complicato ottenere su WinForms. Ad esempio nel campo gestionale, si potranno rappresentare i magazzini attraverso mappe 2D o meshes 3D con colorazioni diverse in base al tempo di giacenza o altri parametri. Il magazzino potrà essere navigato virtualmente e gli operatori avranno un'interfaccia più semplice ed intuitiva rispetto ad un insieme di codici e convenzioni. Anche nell'ambito produttivo le interfaccie potranno mostrare linee di produzione, macchinari, ecc.. dando informazioni sull'andamento dell'attività, delle manutenzioni e anomalie. L'inserimento di una fattura o di una anagrafica,  pur migliorabili, potranno rimanere inalterate. WPF deve essere visto come un valore aggiunto a quanto fino ad ora abbiamo prodotto. In questo senso penso che la spinta verso la realizzazione di applicazioni basate su WPF averrà nel breve periodo e sarà forte al punto da giustificare lo sforzo di apprendimento della tecnologia. Chi comunque ha esperienza con ASP.NET anche se in ambito WinForm usa ancora VB6, sarà agevolato. Quello che invece richiederà maggiori sforzi e sarà più invasivo sugli applicativi esistenti sarà la conformità a UAC, ma questo è un altro discorso...

RE: TechEd Developer - Non siamo gli unici... :-D

In riferimento ai post precedenti #1 e #2.

Non voglio innescare una polemica, ma ritengo che BISOGNA usare le stored procedures, sia per ragioni di sicurezza ma anche per ragioni prestazionali. E' vero però che in alcuni casi le SPs sono molto controproducenti, ad esempio quando si vuole fare una form di ricerca che includa o escluda criteri di filtro. In questo caso infatti la struttura della query non è rigida ma dinamica e allora tanto vale usare statement sql specifici.

Ho scritto una piccola store in SQL 2005 nel database Northwind:

CREATE PROCEDURE [dbo].[GetOrdersByDate]( @StartDate datetime, @EndDate datetime) AS DECLARE @Number int SELECT @Number=COUNT(*) FROM Orders WHERE OrderDate>=@StartDate AND OrderDate<=@EndDate GO

e questo statement di prova, nel quale eseguo 10000 volte la chiamata alla SP e 10000 volte la chiamata ad un analogo statement sql. Ogni chiamata ha parametri diversi.

DECLARE @StartDate datetime DECLARE @EndDate datetime DECLARE @Time datetime DECLARE @i int DECLARE @Query VARCHAR(1000) SET @Time = GETDATE() SET @i = 0 SELECT @StartDate = '2000-01-01' SELECT @EndDate = '2010-01-01' WHILE (@i<10000) BEGIN -- Questo calcolo è inutile qui: serve per avere lo stesso contesto della -- chiamata via sql statement SET @Query ='DECLARE @Number int SELECT @Number=COUNT(*) FROM Orders WHERE OrderDate>=''' + CONVERT(VARCHAR(4), YEAR(@StartDate)) + '-' + CONVERT(VARCHAR(2), MONTH(@StartDate)) + '-' + CONVERT(VARCHAR(2), DAY(@StartDate)) + ''' AND OrderDate<=''' + + CONVERT(VARCHAR(4), YEAR(@EndDate)) + '-' + CONVERT(VARCHAR(2), MONTH(@EndDate)) + '-' + CONVERT(VARCHAR(2), DAY(@EndDate)) + '''' EXECUTE [Northwind].[dbo].[GetOrdersByDate] @StartDate ,@EndDate SET @StartDate = DATEADD(day, 1, @StartDate) SET @i = @i + 1 END SELECT 'Store procedure:' + CAST(DATEDIFF(ms,@Time,GETDATE()) AS VARCHAR(50)) SET @Time = GETDATE() SET @i = 0 SELECT @StartDate = '2000-01-01' SELECT @EndDate = '2010-01-01' WHILE (@i<10000) BEGIN SET @Query ='DECLARE @Number int SELECT @Number=COUNT(*) FROM Orders WHERE OrderDate>=''' + CONVERT(VARCHAR(4), YEAR(@StartDate)) + '-' + CONVERT(VARCHAR(2), MONTH(@StartDate)) + '-' + CONVERT(VARCHAR(2), DAY(@StartDate)) + ''' AND OrderDate<=''' + + CONVERT(VARCHAR(4), YEAR(@EndDate)) + '-' + CONVERT(VARCHAR(2), MONTH(@EndDate)) + '-' + CONVERT(VARCHAR(2), DAY(@EndDate)) + '''' EXECUTE (@Query) SET @StartDate = DATEADD(day, 1, @StartDate) SET @i = @i + 1 END SELECT 'Query:' + CAST(DATEDIFF(ms,@Time,GETDATE()) AS VARCHAR(50))

Risultato: 10000 chiamate a SP in ~560 ms, 10000 chiamate a sql statement in ~16300 ms. Quindi in questo semplice esempio le SP sono ~29 volte più veloci degli statement sql. Quindi, la scelta di cosa usare dipende ancora una volta dal particolare contesto.

Multi-Language Addin for VS

Per quanti hanno patito le pene dell'inferno nel cercare di gestire la localizzazione di grossi progetti winform, consiglio questo addin che per me è diventato oramai indispensabile. Lo trovate qui.

 

L'addin analizza un progetto alla volta della vostra soluzione. Estrae tutte le proprietà localizzabili dei controlli/componenti delle form in una lista, tutte le stringhe presenti nel codice in un'altra lista. In modo molto intuitivo è possibile aggiungere lingue e gestire i contenuti localizzati. Si basa su un proprio database locale, ma esporta in file di risorsa.

 

P.S.: Non lasciatevi spaventare dal sito, il prodotto è fatto molto bene.

Snippet per la lettura di un attributo XML

Molte volte è necessario leggere un file XML in modo programmatico, mappando ad esempio attributi di un nodo xml in campi del proprio object model. Questo snippet di codice permette di leggere un attributo di un nodo, convertirlo nel tipo desiderato e nel caso in cui l'attributo non esista o il relativo valore sia non convertibile nel tipo di destinazione, utilizzare un valore di default.

class XmlHelpers{ public static T GetAttribute<T>(XmlNode node ,string attributeName ,T defaultValue ){ T rtn = defaultValue; XmlAttribute attr = node.Attributes[attributeName]; if (attr != null) { Type type = typeof(T); if (type == typeof(string)) return (T)((object)attr.InnerText); TypeConverter converter = TypeDescriptor.GetConverter(type); try{ object result = converter.ConvertFromString(attr.InnerText); if (result is T) rtn = (T)result; }catch (System.FormatException){} } return rtn; } }

Per richiamarlo posso scrivere ad esempio:

Foo f = new Foo(); f.PropA = XmlHelpers.GetAttribute<bool>(fooNode, "A", false);

Salve a tutti!

Dopo un pò di anni di presenza in ugidotnet ho finalmente deciso di pubblicare il mio blog. Utilizzerò questo spazio per condividere informazioni tecniche e per portare il mio contributo alla comunità di ugi.
«aprile»
domlunmarmergiovensab
31123456
78910111213
14151617181920
21222324252627
2829301234
567891011