deep diving c# 4 (raffaele rialdi)
TRANSCRIPT
Deep diving C# 4.0
Raffaele Rialdi
Twitter: @raffaeler
Email: [email protected]
Articoli e codice: http://www.iamraf.net
Blog: http://blogs.ugidotnet.org/raffaele
Profilo MVP: https://mvp.support.microsoft.com/profile/raffaele
Quando e come si decide di evolvere un linguaggio
• Quando si osserva l'adozione su larga scala di un pattern– Pattern iterator => C# 2.0 introduce "yield"– Filtri su tipi enumerabili => C# 3.0 introduce Linq– Metodi helper statici => C# 3.0 introduce gli extension
method
• L'introduzione di uno statement semplifica uno scenario
• Le novità sono sempre "opt-in" cioè non è obbligatorio usarle
Problemi ricorrenti di oggi in C#
• Uso spinto di reflection– Performance povere anche perché non esiste un
meccanismo di Cache built-in
• Ricerca di una soluzione di scripting nelle applicazioni– Forse ricordate "VBA for Application"...
• Quantità industriale di cast durante l'uso di oggetti COM
• Lo spostamento verso la programmazione dichiarativa
Agenda
• Novità sintattiche di C# 4.0– Named + optional parameters– Omissione ref sulle chiamate COM– Varianza e Covarianza
• DLR– dynamic– expando objects
• COM "No PIA"• Type Equivalence e Type Embedding
Optional e named parameters
• Negli object model COM viene spesso indicato il valore di default di un parametro
• Altrettanto spesso ci sono metodi con un numero molto elevato di parametri
• Optional e named parameters mettono la parola fine• Non era mai stata inserita prima perché complica
notevolmente la risoluzione degli overload– Oggi il driver di queste novità è l'interop e quindi il "costo"
è giustificato
"ref" optional per i metodi COM
• Il modificatore ref può essere omesso su metodi e proprietà dei tipi COM– solo sui tipi COM: per il compilatore sono un caso speciale
• Sarebbe stato impossibile chiedere a tutti i produttori di oggetti COM di ricreare le loro PIA
– il 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: OFFICE
Named parametersOptional parametersOmissione modificatore ref
COVARIANZA E CONTROVARIANZA
Regole e controlli effettuati duranteil passaggio di parametri e/o conversioni
Covarianza e Controvarianza• Si 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 definito
– La Controvarianza permette ad un metodo di avere parametri che siano in una gerarchia più alta rispetto a quello definito
Classe con gerarchia più bassa Automobile
Sportiva
FerrariClasse con gerarchia più alta
DEMO: VARIANZA E CONTROVARIANZA
IL DLR
DLR• Il CLR ha fornito fin'ora un type system di tipo statico e indipendente
dai linguaggi– Il 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 runtime
• Il DLR è un normale assembly che usa il CLR in modo da supportare i tipi dinamici, tipici dei linguaggi dinamici– Iron Python, Iron Ruby, etc.
• Il CLR classico non è stato modificato per supportare DLR• Con il DLR oggi abbiamo queste novità:
– Expression Trees v2– Dynamic Dispatch– Call Site Caching
Dynamic vs. Static
Linguaggidinamici
Semplici e succinti
Typing implicito
Meta-programming(reflection)
Nessuna compilazione
Linguaggistatici
Robusti
Performanti
Tool intelligenti
Migliore scalabilità
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 COM• Office ma non solo• I 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 linguaggi• Python, Ruby, Javascript
– semplifica l'uso di DOM che fanno uso di late binding• Html e XML privi di schema
• Esempio: Silverlight V4
I Binders
• Object Binder– Per default si comporta in modo analogo del binder statico
• Javascript Binder (HTML Dom)• Python Binder• Ruby Binder• COM Binder (pensato per Office)• Custom Binder
Come avviene una call
• Una CallSite per ogni operazione dinamica• La CallSite è l'entità che caratterizza la chiamata
– parametri, nome, tutto il contesto
• La CallSite viene inizializzata in modo Lazy– La prima volta viene calcolata– Le volte successive viene presa da una cache
• Impatto in perf solo sul primo run– È come bruciare una e2prom e poi usarla
• Possiamo definire la CallSite come un gateway tra CLR e DLR
Oggetti dinamicamente tipizzatiCalculator calc = GetCalculator();int sum = calc.Add(10, 20);
object calc = GetCalculator();Type calcType = calc.GetType();object res = calcType.InvokeMember("Add", BindingFlags.InvokeMethod, null, new object[] { 10, 20 });int sum = Convert.ToInt32(res);
ScriptObject calc = GetCalculator();object res = calc.Invoke("Add", 10, 20);int sum = Convert.ToInt32(res);
dynamic calc = GetCalculator();int sum = calc.Add(10, 20);
Tipizzazione statica di un dynamic
Invocazione dinamica del
metodo
Conversionedinamica
Scenari d'uso per il DLRReflection
• Il binder CLR usato dal DLR usa reflection in modo "intelligente"– Reflection.Emit viene usato per generare IL a partire dalle
Expression v2– Tutto quello che viene fatto dopo è identico (jitting, etc.)
• Reflection 'classica' è molto più lenta– no cache– il clr sa già quali overload esistono e come fare il dispatch– in più si possono aggiungere altri binder che risolvono per
python, ruby, com, etc. etc.
Scenari d'uso per il DLR
• Manipolazione di object che vengono da "qualche parte"– Plugin/Addins
• Usando oggetti COM• Usando object model privi di schema (DOM XML,
HTML)• Quando è possibile, prediligere lo static binding– Strong typing significa robustezza del codice– Performance
NO PIA
PIA = Primary Interop Assembly
PIAPrimary Interop Assembly
• Le PIA sono gli assembly wrapper primari che permettono di accedere in modo 'semplice' agli oggetti COM– Creati a partire dalla type library– Necessitano di strong name e di essere registrate in GAC
• Deploy complesso
– Se l'object model è grosso (Office) le PIA hanno dimensioni enormi rapportate all'applicazione che le usa
– Il versioning è un problema• Se 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 PIA– Depoly di PIA di Office 2007 = 6.5MB– Deploy di PIA di Office 2010 = 6.5MB+– Questa versione non funzionerà con Office 2003
• Per 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 PIA– Si 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 PIA
• Invece di una reference alla PIA, avremo un namespace con il codice della PIA all'interno del nostro assembly
• Nei metadati le VTable hanno degli speciali marker ("_VtblGap1_10") che informano il CLR quanti elementi della VTable sono da saltare– il numero 1 è l'indice, il numero 10 è il numero di elementi
da saltare
Come avviene l'Embedding
• L'embedding riguarda solo i metadati– No codice IL, classi o metodi statici– Solo interfacce con attributi ComImport e Guid, delegate,
struct semplici, enum– Solo i tipi in assembly marcati con:
• [assembly:Guid(...)] e• [assembly:ImportedFromTypeLib(...)]
Type Equivalence
• La Type Equivalence è una diretta conseguenza della possibilità di eseguire l'embedding
interface ITask{
// ...}
interface ITask{
// ...}
interface ITask{
// ...}
embedding embedding
Assembly A
Assembly X Assembly Y
typeequivalenti
E se ...(Type Embedding & Equivalence)
• Ignoriamo COM• Facciamo 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
architettura
• Scopriamo nella demo cosa succede
Evoluzione di C#.N
ET 4.0
.NET 3.5
DLR2
LINQ
DLRLanguage features
Expression trees
Expressiontrees v2
Call site caching
Dynamicdispatch
Silverlight
.NET 2.0
GenericsFast
delegatesDynamicmethods
Script hosting
Compiler asa Service Async
.NET 1.0
GC
BCL
ReflectionJIT
Code generation
Verifiersandbox
???
Cosa arriverà ...
• Async "Syntactic Sugar" per esecuzione asincrona• Compiler as a service– Eval di codice a runtime
• Expression v2 usabili da codice– Evoluzione delle expression di Linq– MultiStatement– E magari che possano essere ricavate senza costruire il tree
a mano
• VB e C# allineati
Domande ?