Deep diving C# 4.0Raffaele RialdiTwitter: @raffaelerEmail:malta@vevy.comArticoli e codice: http://www.iamraf.netBlog:http://blogs.ugidotnet.org/raffaeleProfilo MVP:https://mvp.support.microsoft.com/profile/raffaele
Quando e come si decide di evolvere un linguaggioQuando si osserva l'adozione su larga scala di un patternPattern iterator => C# 2.0 introduce "yield"Filtri su tipi enumerabili => C# 3.0 introduce LinqMetodi helper statici => C# 3.0 introduce gli extension methodL'introduzione di uno statement semplifica uno scenarioLe novità sono sempre "opt-in" cioè non è obbligatorio usarle
Problemi ricorrenti di oggi in C#Uso spinto di reflectionPerformance povere anche perché non esiste un meccanismo di Cache built-inRicerca di una soluzione di scripting nelle applicazioniForse ricordate "VBA for Application"...Quantità industriale di cast durante l'uso di oggetti COMLo spostamento verso la programmazione dichiarativa
AgendaNovità sintattiche di C# 4.0Named + optional parametersOmissione ref sulle chiamate COMVarianza e CovarianzaDLRdynamicexpando objectsCOM "No PIA"Type Equivalence e Type Embedding
Optional e named parametersNegli object model COM viene spesso indicato il valore di default di un parametroAltrettanto spesso ci sono metodi con un numero molto elevato di parametriOptional e named parameters mettono la parola fineNon era mai stata inserita prima perché complica notevolmente la risoluzione degli overloadOggi il driver di queste novità è l'interop e quindi il "costo" è giustificato
"ref" optional per i metodi COMIl modificatore ref può essere omesso su metodi e proprietà dei tipi COMsolo sui tipi COM: per il compilatore sono un caso specialeSarebbe stato impossibile chiedere a tutti i produttori di oggetti COM di ricreare le loro PIAil compilatore permette il "trucco" se sulla dichiarazione del Type esiste l'attributo [ComImport]MyCOMObject app = new MyCOMObject(); object m = string.Empty; app.MyMethod(ref m, ref m, ref m, ref m); MyCOMObject app = new MyCOMObject(); app.MyMethod(m, m, m, m);
Demo: OfficeNamed parametersOptional parametersOmissione modificatore ref
Covarianza e ControvarianzaRegole e controlli effettuati duranteil passaggio di parametri e/o conversioni
Covarianza e ControvarianzaSi applica solo ad interface e delegate con generics i cui parametri sono di tipo reference
In una operazione di conversione o regola di compilazione  ...La Covarianza permette ad un metodo di avere un tipo di ritorno più basso nella gerarchia di derivazione rispetto a quello definitoLa Controvarianza permette ad un metodo di avere parametri che siano in una gerarchia più alta rispetto a quello definitoClasse con gerarchia più bassaClasse con gerarchia più alta
DEMO: Varianza e controvarianza
Il DLR
DLRIl CLR ha fornito fin'ora un type system di tipo statico e indipendente dai linguaggiIl supporto ai tipi dinamici via Reflection è povero e poco performante.Il DLR è una sorta di "API" sopra il CLR che permette di spostare il controllo sui tipi (binding) al runtimeIl DLR è un normale assembly che usa il CLR in modo da supportare i tipi dinamici, tipici dei linguaggi dinamiciIron Python, Iron Ruby, etc.Il CLR classico non è stato modificato per supportare DLRCon il DLR oggi abbiamo queste novità:Expression Trees v2Dynamic DispatchCall Site Caching
Dynamic vs. Static
DLR: perché e perché oggi?Non è solo un revival del "late binding"!Il motivo per l'introduzione di questa API è l'interoperabilitàsemplifica l'interazione con componenti COMOffice ma non soloI cast che sono necessari oggi non rendono più sicuro il codice perché c'è sempre la possibilità in un InvalidCastException a runtime. Quindi dynamic non impoverisce la stabilità in questi scenari.semplifica il mix con altri linguaggiPython, Ruby, Javascriptsemplifica l'uso di DOM che fanno uso di late bindingHtml e XML privi di schemaEsempio: Silverlight V4
I BindersObject BinderPer default si comporta in modo analogo del binder staticoJavascript Binder (HTML Dom)Python BinderRuby BinderCOM Binder (pensato per Office)Custom Binder
Come avviene una callUna CallSite per ogni operazione dinamicaLa CallSite è l'entità che caratterizza la chiamataparametri, nome, tutto il contestoLa CallSite viene inizializzata in modo LazyLa prima volta viene calcolataLe volte successive viene presa da una cacheImpatto in perf solo sul primo runÈ come bruciare una e2prom e poi usarlaPossiamo definire la CallSite come un gateway tra CLR e  DLR
Oggetti dinamicamente tipizzatiCalculator calc = GetCalculator();int sum = calc.Add(10, 20);object calc = GetCalculator();TypecalcType = calc.GetType();object res = calcType.InvokeMember("Add",BindingFlags.InvokeMethod, null,newobject[] { 10, 20 });int sum = Convert.ToInt32(res);ScriptObject calc = GetCalculator();object res = calc.Invoke("Add", 10, 20);int sum = Convert.ToInt32(res);Tipizzazione statica di un dynamicdynamic calc = GetCalculator();int sum = calc.Add(10, 20);Invocazione dinamica del metodoConversionedinamica
Scenari d'uso per il DLRReflectionIl binder CLR usato dal DLR usa reflection in modo "intelligente"Reflection.Emit viene usato per generare IL a partire dalle Expression v2Tutto quello che viene fatto dopo è identico (jitting, etc.)Reflection 'classica' è molto più lentano cacheil clr sa già quali overload esistono e come fare il dispatchin più si possono aggiungere altri binder che risolvono per python, ruby, com, etc. etc.
Scenari d'uso per il DLRManipolazione di object che vengono da "qualche parte"Plugin/AddinsUsando oggetti COMUsando object model privi di schema (DOM XML, HTML)Quando è possibile, prediligere lo static bindingStrong typing significa robustezza del codicePerformance
NO PIAPIA = Primary Interop Assembly
PIAPrimary Interop AssemblyLe PIA sono gli assembly wrapper primari che permettono di accedere in modo 'semplice' agli oggetti COMCreati a partire dalla type libraryNecessitano di strong name e di essere registrate in GACDeploy complessoSe l'object model è grosso (Office) le PIA hanno dimensioni enormi rapportate all'applicazione che le usaIl versioning è un problemaSe sviluppo con le PIA di Office 2007, non funziona sulla 2003
"no PIA" per COM"no PIA" è una feature che permette di eseguire l'embedding in un assembly del codice di una PIADepoly di PIA di Office 2007 = 6.5MBDeploy di PIA di Office 2010 = 6.5MB+Questa versione non funzionerà con Office 2003Per risolvere questo problema nel CLR 4.0 è stato introdotto il "Type Embedding" (o "No PIA") e la "Type Equivalence"i compilatori hanno un nuovo switch /link per fare l'embedding del solo codice usato di una PIASi basa su un nuovo attributo, [TypeIdentifier] che grazie al [Guid] già usato in COM, permette di dire al CLR che due tipi sono "Equivalenti"
Type Embedding (No PIA)Vengono creati nuovi tipi, copie parziali dei tipi completi presenti nella PIAInvece di una reference alla PIA, avremo un namespace con il codice della PIA all'interno del nostro assemblyNei metadati le VTable hanno degli speciali marker ("_VtblGap1_10") che informano il CLR quanti elementi della VTable sono da saltareil numero 1 è l'indice, il numero 10 è il numero di elementi da saltare
Come avviene l'EmbeddingL'embedding riguarda solo i metadatiNo codice IL, classi o metodi staticiSolo interfacce con attributi ComImport e Guid, delegate, struct semplici, enumSolo i tipi in assembly marcati con:[assembly:Guid(...)]   e[assembly:ImportedFromTypeLib(...)]
Type EquivalenceLa Type Equivalence è una diretta conseguenza della possibilità di eseguire l'embeddingAssembly Ainterface ITask{	// ...}embeddingembeddinginterface ITask{	// ...}interface ITask{	// ...}Assembly XAssembly Ytypeequivalenti
E se ...(Type Embedding & Equivalence)Ignoriamo COMFacciamo finta di referenziare una type library che non c'èEseguiamo l'embedding dell'assembly più scomodo che ci sia: il classico "Common.dll"Contiene tipicamente le interfacce condivise in una architetturaScopriamo nella demo cosa succede
Evoluzione di C#DLR2Script hostingCompiler asa ServiceAsync???.NET 4.0DLRExpressiontrees v2Call site cachingDynamicdispatch.NET 3.5LINQLanguage featuresExpression treesSilverlight.NET 2.0GenericsFastdelegatesDynamicmethods.NET 1.0GCReflectionJITBCLCode generationVerifiersandbox
Cosa arriverà ...Async  "Syntactic Sugar" per esecuzione asincronaCompiler as a serviceEval di codice a runtimeExpression v2 usabili da codiceEvoluzione delle expression di LinqMultiStatementE magari che possano essere ricavate senza costruire il tree a manoVB e C# allineati

Deep diving C# 4 (Raffaele Rialdi)

  • 1.
    Deep diving C#4.0Raffaele RialdiTwitter: @raffaelerEmail:malta@vevy.comArticoli e codice: http://www.iamraf.netBlog:http://blogs.ugidotnet.org/raffaeleProfilo MVP:https://mvp.support.microsoft.com/profile/raffaele
  • 2.
    Quando e comesi decide di evolvere un linguaggioQuando si osserva l'adozione su larga scala di un patternPattern iterator => C# 2.0 introduce "yield"Filtri su tipi enumerabili => C# 3.0 introduce LinqMetodi helper statici => C# 3.0 introduce gli extension methodL'introduzione di uno statement semplifica uno scenarioLe novità sono sempre "opt-in" cioè non è obbligatorio usarle
  • 3.
    Problemi ricorrenti dioggi in C#Uso spinto di reflectionPerformance povere anche perché non esiste un meccanismo di Cache built-inRicerca di una soluzione di scripting nelle applicazioniForse ricordate "VBA for Application"...Quantità industriale di cast durante l'uso di oggetti COMLo spostamento verso la programmazione dichiarativa
  • 4.
    AgendaNovità sintattiche diC# 4.0Named + optional parametersOmissione ref sulle chiamate COMVarianza e CovarianzaDLRdynamicexpando objectsCOM "No PIA"Type Equivalence e Type Embedding
  • 5.
    Optional e namedparametersNegli object model COM viene spesso indicato il valore di default di un parametroAltrettanto spesso ci sono metodi con un numero molto elevato di parametriOptional e named parameters mettono la parola fineNon era mai stata inserita prima perché complica notevolmente la risoluzione degli overloadOggi il driver di queste novità è l'interop e quindi il "costo" è giustificato
  • 6.
    "ref" optional peri metodi COMIl modificatore ref può essere omesso su metodi e proprietà dei tipi COMsolo sui tipi COM: per il compilatore sono un caso specialeSarebbe stato impossibile chiedere a tutti i produttori di oggetti COM di ricreare le loro PIAil compilatore permette il "trucco" se sulla dichiarazione del Type esiste l'attributo [ComImport]MyCOMObject app = new MyCOMObject(); object m = string.Empty; app.MyMethod(ref m, ref m, ref m, ref m); MyCOMObject app = new MyCOMObject(); app.MyMethod(m, m, m, m);
  • 7.
    Demo: OfficeNamed parametersOptionalparametersOmissione modificatore ref
  • 8.
    Covarianza e ControvarianzaRegolee controlli effettuati duranteil passaggio di parametri e/o conversioni
  • 9.
    Covarianza e ControvarianzaSiapplica solo ad interface e delegate con generics i cui parametri sono di tipo reference
  • 10.
    In una operazionedi conversione o regola di compilazione ...La Covarianza permette ad un metodo di avere un tipo di ritorno più basso nella gerarchia di derivazione rispetto a quello definitoLa Controvarianza permette ad un metodo di avere parametri che siano in una gerarchia più alta rispetto a quello definitoClasse con gerarchia più bassaClasse con gerarchia più alta
  • 11.
    DEMO: Varianza econtrovarianza
  • 12.
  • 13.
    DLRIl CLR hafornito fin'ora un type system di tipo statico e indipendente dai linguaggiIl supporto ai tipi dinamici via Reflection è povero e poco performante.Il DLR è una sorta di "API" sopra il CLR che permette di spostare il controllo sui tipi (binding) al runtimeIl DLR è un normale assembly che usa il CLR in modo da supportare i tipi dinamici, tipici dei linguaggi dinamiciIron Python, Iron Ruby, etc.Il CLR classico non è stato modificato per supportare DLRCon il DLR oggi abbiamo queste novità:Expression Trees v2Dynamic DispatchCall Site Caching
  • 14.
  • 15.
    DLR: perché eperché oggi?Non è solo un revival del "late binding"!Il motivo per l'introduzione di questa API è l'interoperabilitàsemplifica l'interazione con componenti COMOffice ma non soloI cast che sono necessari oggi non rendono più sicuro il codice perché c'è sempre la possibilità in un InvalidCastException a runtime. Quindi dynamic non impoverisce la stabilità in questi scenari.semplifica il mix con altri linguaggiPython, Ruby, Javascriptsemplifica l'uso di DOM che fanno uso di late bindingHtml e XML privi di schemaEsempio: Silverlight V4
  • 16.
    I BindersObject BinderPerdefault si comporta in modo analogo del binder staticoJavascript Binder (HTML Dom)Python BinderRuby BinderCOM Binder (pensato per Office)Custom Binder
  • 17.
    Come avviene unacallUna CallSite per ogni operazione dinamicaLa CallSite è l'entità che caratterizza la chiamataparametri, nome, tutto il contestoLa CallSite viene inizializzata in modo LazyLa prima volta viene calcolataLe volte successive viene presa da una cacheImpatto in perf solo sul primo runÈ come bruciare una e2prom e poi usarlaPossiamo definire la CallSite come un gateway tra CLR e DLR
  • 18.
    Oggetti dinamicamente tipizzatiCalculatorcalc = GetCalculator();int sum = calc.Add(10, 20);object calc = GetCalculator();TypecalcType = calc.GetType();object res = calcType.InvokeMember("Add",BindingFlags.InvokeMethod, null,newobject[] { 10, 20 });int sum = Convert.ToInt32(res);ScriptObject calc = GetCalculator();object res = calc.Invoke("Add", 10, 20);int sum = Convert.ToInt32(res);Tipizzazione statica di un dynamicdynamic calc = GetCalculator();int sum = calc.Add(10, 20);Invocazione dinamica del metodoConversionedinamica
  • 19.
    Scenari d'uso peril DLRReflectionIl binder CLR usato dal DLR usa reflection in modo "intelligente"Reflection.Emit viene usato per generare IL a partire dalle Expression v2Tutto quello che viene fatto dopo è identico (jitting, etc.)Reflection 'classica' è molto più lentano cacheil clr sa già quali overload esistono e come fare il dispatchin più si possono aggiungere altri binder che risolvono per python, ruby, com, etc. etc.
  • 20.
    Scenari d'uso peril DLRManipolazione di object che vengono da "qualche parte"Plugin/AddinsUsando oggetti COMUsando object model privi di schema (DOM XML, HTML)Quando è possibile, prediligere lo static bindingStrong typing significa robustezza del codicePerformance
  • 21.
    NO PIAPIA =Primary Interop Assembly
  • 22.
    PIAPrimary Interop AssemblyLePIA sono gli assembly wrapper primari che permettono di accedere in modo 'semplice' agli oggetti COMCreati a partire dalla type libraryNecessitano di strong name e di essere registrate in GACDeploy complessoSe l'object model è grosso (Office) le PIA hanno dimensioni enormi rapportate all'applicazione che le usaIl versioning è un problemaSe sviluppo con le PIA di Office 2007, non funziona sulla 2003
  • 23.
    "no PIA" perCOM"no PIA" è una feature che permette di eseguire l'embedding in un assembly del codice di una PIADepoly di PIA di Office 2007 = 6.5MBDeploy di PIA di Office 2010 = 6.5MB+Questa versione non funzionerà con Office 2003Per risolvere questo problema nel CLR 4.0 è stato introdotto il "Type Embedding" (o "No PIA") e la "Type Equivalence"i compilatori hanno un nuovo switch /link per fare l'embedding del solo codice usato di una PIASi basa su un nuovo attributo, [TypeIdentifier] che grazie al [Guid] già usato in COM, permette di dire al CLR che due tipi sono "Equivalenti"
  • 24.
    Type Embedding (NoPIA)Vengono creati nuovi tipi, copie parziali dei tipi completi presenti nella PIAInvece di una reference alla PIA, avremo un namespace con il codice della PIA all'interno del nostro assemblyNei metadati le VTable hanno degli speciali marker ("_VtblGap1_10") che informano il CLR quanti elementi della VTable sono da saltareil numero 1 è l'indice, il numero 10 è il numero di elementi da saltare
  • 25.
    Come avviene l'EmbeddingL'embeddingriguarda solo i metadatiNo codice IL, classi o metodi staticiSolo interfacce con attributi ComImport e Guid, delegate, struct semplici, enumSolo i tipi in assembly marcati con:[assembly:Guid(...)] e[assembly:ImportedFromTypeLib(...)]
  • 26.
    Type EquivalenceLa TypeEquivalence è una diretta conseguenza della possibilità di eseguire l'embeddingAssembly Ainterface ITask{ // ...}embeddingembeddinginterface ITask{ // ...}interface ITask{ // ...}Assembly XAssembly Ytypeequivalenti
  • 27.
    E se ...(TypeEmbedding & Equivalence)Ignoriamo COMFacciamo finta di referenziare una type library che non c'èEseguiamo l'embedding dell'assembly più scomodo che ci sia: il classico "Common.dll"Contiene tipicamente le interfacce condivise in una architetturaScopriamo nella demo cosa succede
  • 28.
    Evoluzione di C#DLR2ScripthostingCompiler asa ServiceAsync???.NET 4.0DLRExpressiontrees v2Call site cachingDynamicdispatch.NET 3.5LINQLanguage featuresExpression treesSilverlight.NET 2.0GenericsFastdelegatesDynamicmethods.NET 1.0GCReflectionJITBCLCode generationVerifiersandbox
  • 29.
    Cosa arriverà ...Async "Syntactic Sugar" per esecuzione asincronaCompiler as a serviceEval di codice a runtimeExpression v2 usabili da codiceEvoluzione delle expression di LinqMultiStatementE magari che possano essere ricavate senza costruire il tree a manoVB e C# allineati
  • 30.