agosto 2004 Blog Posts
Un frammento interessante da una mail di Paolo Arvati, che ho pensato potrebbe interessare anche una comunità .NET come la nostra:
"Molti nell'ambito Java/J2EE stanno chiedendo e proponendo innovazioni (annotations, AOP) in modo da rendere lo sviluppo facile e veloce come in
.NET.
Inoltre, molti creatori di framework e sistemi enterprise focalizzano sempre meno l'attenzione e il marketing su Java e J2EE e le loro
features avanzate. I problemi delle features avanzate se li deve porre chi crea un framework, chi crea un application server, chi crea un aspect per l'AOP, chi crea un prodotto per...
Mi sa che il rientro non è ancora finito per tutti, quindi conviene magari posticipare la chiusura del "Test di buon rientro" per la fine della prossima settimana.
Per adesso ho ricevuto solo un feedback e mezzo e la domanda secondo me è troppo interessante per non godervela in tanti :-)
Ho scoperto dal post "GUI patterns" di Jeff Atwood, questo meraviglioso sito di Martijn van Welie. E' d'obbligo navigarlo per bene!
Perché IKVM.NET si chiama IKVM.NET? La risposta arriva direttamente da Jeroen Frijters, il suo autore, in una mail di oggi:
"Originally it was I<<K.VM.NET, too make fun of the fact that Sun prefixes everything with a J, but Radio (my weblog software at the time) didn't like the << characters.".
Da questo post di S. Somasegar (Corporate VP, Developer Division) scopro quanto dura fare il build della Beta1 di VS 2005: più di 30 ore!!!...
Il seguente snippet compila:
using System;class Foo{ [Obsolete("", true)] static void Main() { Console.WriteLine("Hello Obsolete World!"); Console.Read(); }}
Ciò vuol dire che l'entrypoint Main non può mai essere Obsolete. Questo sicuramente ha senso, però mi aspettavo di vedere un warning oppure una nota a riguardo nelle specifiche.
A tutti string.Empty potrebbe sembrare un'espressione costante, ma in senso C# non lo è!
Empty è definito come campo static readonly e non come const, perciò non è una "constant expression" (C# Language Specification, 14.15).
Una conseguenza di questo fatto? Il seguente banalissimo snippet non compila!
using System;class FooAttribute: Attribute{ public FooAttribute(string arg){}}class Test{ [Foo(string.Empty)] static void DoSomething() { Console.WriteLine("I did something"); } static void Main() { DoSomething(); Console.Read(); }}
Otteniamo errore di compilazione: "An attribute argument must be a constant expression, typeof expression or array creation expression" e dobbiamo sostituire string.Empty con "" oppure con null.
Strano, vero?
In un post di due settimane fa segnalavo la possibilità di creare classi proxy dinamiche in .NET con NMock. Siccome ho l'intenzione di scriverci un articolo, non appena troverò una finestra di tempo, mi sono preparato la tabella qui sotto che riassume lo stato dell'arte dei progetti open-source che implementano in .NET la creazione di classi proxy dinamiche
J2SE (questa riga serve da confronto con i progetti qui sotto)
Sun Microsystems
java.lang.reflect.InvocationHandler
java.lang.reflect.Proxy
Progetto
Autore
Classi
NMock
Joe Walnes
NMock.IInvocationHandler
NMock.Dynamic.ClassGenerator
Apache Avalon Castle DynamicProxy
Hamilton Verissimo de Oliveira
Apache.Avalon.DynamicProxy.IInvocationHandler
Apache.Avalon.DynamicProxy.ProxyGenerator
DynaProx.NET
Sébastien Bouchet
DynaProx.Framework.CallHandler
DynaProx.Framework.ObjectFactory
CIL Programming: Under the Hood of .NET (libro)
Jason Bock
Proxies.InvocationHandler
Proxies.Proxy
Così nel frattempo può servire anche a voi.
Aggiornamento (23/08): Ho cambiato l'impostazione della tabella, grazie ad...
using System;using System.Collections;class Foo{ static void Main() { Hashtable table = new Hashtable(); int intKey = 50; long longKey = 50; table.Add(intKey, "SomeValue"); table.Add(longKey, "SomeValue"); Console.WriteLine(table.Count); Console.Read(); }}
Cosa viene visualizzato a console?
A. 1
B. 2
C. errore a run-time: System.ArgumentException, Item has already been added. Key in dictionary: "50" Key being added: "50"
Per una buona digestione delle vacanze, pensate a dichiarare e inizializzare x e y in modo da avere:
x += y; // un'assegnazione correttax = x + y; // errore di compilazione
Gli autori (Joshua Bloch e Neal M. Gafter) hanno pensato il quiz per Java, ma io ve lo propongo per C# - i comportamenti Java e C# in questo caso sono diversi tra loro, perciò ho rubato solo il testo del quiz, non la soluzione.
Apprezzerò nei vostri feedback le spiegazioni migliori e le posterò verso la metà della prossima settimana (dipende anche da in quanti mi risponderete).
Non capisco perché nella pagina di Yahoo! Italia Notizie Attualità:
il link "Immigrazione" punta su "clandestini.html"
il link "La giustizia in Italia" punta su "processosme.html"
il link "Lavoro" punta su "pensioni.html"
il link "Economia italiana" punta su "inflazione.html"
il link "Afghanistan" punta su "taleban.html"
il link "La Microsoft" punta su "gates.html"
il link "Virus informatici" punta su "goner.html"
il link " Mafia e Camorra" punta su "provenzano.html".
using System;class Test{ static void DoIt(int a, long b, long c) { Console.WriteLine("In DoIt(int, long, long)"); } static void DoIt(int a, int b, long c) { Console.WriteLine("In DoIt(int, int, long)"); } static void Main() { DoIt(1, 2, 3); Console.Read(); }}
What is the result of compiling and executing the above code?
A. Prints "In DoIt(int, long, long)"
B. Prints "In DoIt(int, int, long)"
C. Compiler Error
D. Run-Time Error
In Java si ottiene lo stesso risultato - guardate solo dopo aver pensato ad una risposta :-)
Grady Booch, uno dei tre famosi "Three Amigos", ha raccolto una lista equilibratissima e di finissimo palato di siti dedicati all'architettura software. La riposto qui sotto per chi ha troppa fretta per registrarsi sul sito di Booch:
AcademicSoftware Engineering Institute -> Software ArchitectureUniversity of California, Irvine -> Institute for Software Research -> Software Architecture ResearchUniversity of Illinois, Urbana-Champaign -> The Software Architecture GroupUniversity of Southern California -> Software Architecture GroupUniversity of Stuttgart -> Project BauhausUniversity of Texas -> Product-Line Architecture Research GroupUniversity of Waterloo -> Software Architecture Group
CommercialBredemeyer ConsultingIBM -> IBM Patterns for e-businessMicrosoft -> Microsoft Architects JOURNALPhilips -> Gaudí System...
Un paragrafo (p. 72) dal libro "Expert One-on-One Visual Basic .NET Business Objects" di Rockford Lhotka (MVP, Regional Director e Software Legend - cosa gli manca?) che viene a completare quello che è stato detto in questo post "Lettura dei dati e DbNull" del nostro M.rkino (MVP anche lui):
"Most of the time, we don't care about the difference between a null value and an empty value (such as an empty string or a zero), but databases often do. When we're retrieving data from a database, we need to handle the occurence of unexpected null values with code such as this:
If...
Non mi vergogno di dire che ho scoperto solo stasera il "Clipboard Ring".
Vi ricordate come Jay Roxe al "Whidbey Reloaded" del 8 luglio trascinava dal Toolbar pezzi di codice nella sua presentazione? A mio parere è comodissimo per gli speaker - si potrebbe sperimentare al prossimo workshop.
Che valore ha la seguente espressione?
System.Convert.ToBase64String(new byte[3]).TrimEnd('=').Split('A').Length
A. 3
B. 4
C. 5
Sono stato curioso di vedere quali blog di UGIdotNET legge Robert Scoble. Complimenti a: Andrea Saltarello, Corrado Cavalli, Raffaele Rialdi, Emanuele DelBono, Davide Bedin.
Oggi quando ho postato della nonna, mi è sfuggito il nonno... il signore Donald William Bray :-)
Intanto che ci siamo, ho fatto subscribe al blog di Tim Bray, il tizio che inventò nel 1996 l'XML e oggi Technology Director a Sun. Il blog non è tecnico però è pieno di cose tenere; fra le tante, a me è piaciuta questa frase:
Poetry is like blogging; more write it than read it.
Curiosi di sapere qual è stata la prima frase SELECT (a quei tempi, esattamente 30 anni fa, SQL si chiamava SEQUEL, da Structured English QUEry Language)?
Find the names of employees in the toy department.
SELECT NAMEFROM EMPWHERE DEPT = 'TOY'
The mapping returns the entire set of names which qualify according to the test DEPT = 'TOY'.
Scritta ovviamente proprio dai due creatori di SQL: Donald D. Chamberlin e Raymond F. Boyce. Se volete leggerla col font di 30 anni fa, la trovate qui alla pagina 253 (pagina 5 del PDF).
Vi ricordate il mio post sulla bisnonna di Java (la signora Margaret Carolyn (Svensdötter) Morrison)? Oggi mi tocca presentarvi la nonna dell'XML, la signora Jean Bray (mamma del co-padre dell'XML, Tim Bray).
Una soluzione bellissima per fare single-stepping a livello IL, postata sulla ADVANCED-DOTNET mailing list di DevelopMentor da Serge Lidin (l'autore dell'"Inside Microsoft .NET IL Assembler")
Supponiamo di voler fare il debugging a livello IL di un programma Foo.cs. Dovremo procedere nel seguente modo (ho scelto una modalità da linea di comando per capire meglio i passi):
1. Visual C# .NET Compiler (Emit debugging information)csc Foo.cs /debug+
2. .NET Framework IL Disassembler (Show original source lines as comments, Compile to file with specified name)ildasm Foo.exe /source /out=Foo.il
3. .NET Framework IL Assembler (Include debug information)ilasm Foo.il /debug
4. Development Environment (Open the specified executable to be...
Abbiamo visto ieri, grazie all'osservazione di Nicu, che le specifiche avrebbero dovuto dire:
"Any of the static members declared by the class are referenced" al posto di:
"Any of the static members of the class are referenced".
Curioso, sono ricorso al libro di Richter e ho scoperto che lui fa la precisazione (p. 188) che manca nelle specifiche: quando parla di campo statico, aggiunge "non ereditato"! A Box invece, manca (p. 62) questa precisazione.
Ieri per tutto il giorno vi ho parlato dell'articolo di Nicu G. Fruja in cui porta alla luce "a few gaps and mistakes in the C# reference manual, inconsistencies with different implementations of C#". Gli ho scritto chiedendogli dei commenti su "The reference of the static field B.x triggers only the initialization of A" e oggi mi ha risposto così (traduco dal rumeno):
Le specifiche affermano erroneamente che:
(17.11) "The execution of a static constructor is triggered by the first of the following events to occur within an application domain:
An instance of the class is created.
Any of the static members...
Interessante l'osservazione di Michael Geary sulle Class Naming Guidelines. Non ci avevo mai pensato :-)
Per chi non ha fatto ancora subscribe al blog di Michael Geary, conviene che legga il suo resume...
Per arrivare a Google Microsoft Search dalla homepage di Google devi passare prima da more >> e poi da Special Google Searches, e mi sembra corretto. Quello che non capisco è l'icona troppo speciale di questa sezione "Special Searches"...
"it is useful to think of static members as belonging to classes" (C# Language Specification, 17.2.5). Nel nostro caso (B.x), la classe è A. Si può vedere anche dal codice IL:
ldsfld int32 A::x
E' quindi naturale che si chiami il costruttore statico della classe A e non quello della classe B...
Tanti italiani mi hanno chiesto qual è uno dei piatti tipici del mio paese. Se la cucina rumena avesse almeno un centesimo dei piatti di quella italiana, allora ragazzi la cucina rumena sarebbe già famosa nel mondo! :-) Io vado matto per quello che si chiama borsh - una specie di minestra con tantissime verdure, buttate lì a caso. D'estate lo mangio freddo, appena tirato fuori dal frigor (avete notato che dico anch'io frigor e non frigo?). Il bello è che questo minestrone non si fa con acqua ma con un brodo di crusca fermentata, lasciata a macerarsi da belle...
Avrei potuto proporlo come quiz, ma poi mi sono chiesto: "Perché essere sadici?" :-)
using System;class A{ public static int x; static A() { Console.WriteLine("Initializing A"); }}class B: A{ static B() { Console.WriteLine("Initializing B"); }}class Test{ static void Main() { Console.WriteLine("B.x = {0}", B.x); }}
Veramente non riesco a spiegarmi il fatto che questo snippet stampi:
Initializing AB.x = 0
Perché A??? Magari chiedo a Nicu e poi ve lo dico, se mi risponde :-)
Se qualcuno trova una spiegazione, varebbe la pena di postarla!
Se ci fosse stato class al post di struct, questo snippet:
using System;struct P{ static P() { Console.WriteLine("Initializing P"); }}class Test{ static void Main() { P p = new P(); }}
avrebbe stampato a console "Initializing P". Così invece, non stampa nulla! Dobbiamo quindi fare attenzione alla parola class in questo frammento di C# Language Specification (17.11):
"The execution of a static constructor is triggered by the first of the following events to occur within an application domain:
An instance of the class is created.
Any of the static members of the class are referenced."
"The creation of the struct instance p using the parameterless default instance constructor P() does not trigger the...
Questo snippet che può sembrare banale:
using System;class Test{ static void Main() { int[,][] a = new int[2,3][]; Console.WriteLine(a.GetType()); Console.Read(); }}
stampa a console System.Int32[][,] - magari qualcuno di noi si aspettava System.Int32[,][] :-)
using System;class A{ public virtual void M(int i) { Console.WriteLine("A::M(int) called"); }}class B: A{ public override void M(int i) { Console.WriteLine("B::M(int) called"); } public void M(long i) { Console.WriteLine("B::M(long) called"); }}class Test{ static void Main() { B b = new B(); int i = 0; b.M(i); }}
Cosa viene visualizzato a console? Qui non abbiamo C ma non vuol per niente dire che sia più semplice! :-)
A. B::M(long) called
B. B::M(int) called
using System;class Test{ static void Main() { int i; try { goto lab; } finally { i = 3; } lab: Console.WriteLine("i = {0}", i); }}
Vi aspettate:
A. Dipende dalla versione del Framework
B. i = 3
C. Errore di compilazione ("Use of unassigned local variable 'i'")
using System;class A{ public int x; static A(){}}class Test{ static void Main() { A a = null; int i = 0; a.x = a.x + 1/i; }}
Vi aspettate:
A. System.NullReferenceException
B. System.DivideByZeroException
C. Errore di compilazione ("Division by constant zero")
Un assolutamente fantastico articolo del mio connazionale Nicu Georgian Fruja, Research Assistant all'Institute of Theoretical Computer Science, ETH Zurigo, purtroppo a pagamento (costa 15$):
N.G. Fruja, "Specification and Implementation Problems for C#", Lecture Notes in Computer Science, Volume 3052 (2004), pp. 127 - 143
Per darvi un assaggio di questa meraviglia, ecco il link per le 9 pagine free dell'appendice che comprendono 17 quiz tostissimi! Perché ne parlo così entusiasta? Un frammento dell'abstract:
"[...] We tried to directly and faithfully reflect the intuitions and design decisions which are expressed in the C# Language Specification. This work [...] brought to light a few gaps...
Giocando con la decorazione con .entrypoint, ho fatto dei piccoli esperimenti.
In sostanza, in questi esperimenti, ho spostato la direttiva .entrypoint dal metodo Main al metodo MyMain, come vedrete negli esempi seguenti. Tutti i metodi MyMain li ho volutamente scelti con la signatura "sbagliata". Le signature corrette sono (secondo la "C# Language Specification", 10.1):
static void Main()
static void Main(string[] args)
static int Main()
static int Main(string[] args)
Sono partito da questa:
class Foo{ public static string MyMain() { return "Hello World"; } static void Main() { }}
Dopo il classico giro csc->ildasm->ilasm e poi esecuzione, ho incontrato in tutti gli esempi questo errore a runtime: System.MethodAccessException ma con differenti informazioni aggiuntive...
Sabato scorso, Stefano ha richiamato sul suo blog il mio post "Main non public?" in cui mi chiedevo "qual è la ragione per cui un metodo Main possa avere qualunque accessibilità...". E' passata una settimana e nessuno ha risposto. Provo allora io a dare una risposta.
Mi sono creato un file Foo.cs:
class Foo{ static void Main() { }}
Con:
csc Foo.cs
ho ottenuto l'eseguibile Foo.exe. L'ho passato poi a ildasm:
ildasm Foo.exe /out=Foo.il
per ottenere il codice IL:
.assembly extern mscorlib{ .publickeytoken = (B7 7A 5C 56 19 34 E0 89 ) .ver 1:0:5000:0}.assembly Foo{ .hash algorithm 0x00008004 .ver 0:0:0:0}.module Foo.exe.imagebase 0x00400000.subsystem 0x00000003.file alignment 512.corflags 0x00000001.class private auto ansi beforefieldinit Foo extends [mscorlib]System.Object{}.class private...
"adrianflorea lives here or, at least, his quizzes do". Ne ho postati solo i primi 3 dei 29 che sono riuscito finora ad immaginare - tanto per vedere come funziona Quizilla. Un po' bruttino, però comodo :-)
A partire da J2SE 1.3, Java ha una classe molto interessante: java.lang.reflect.Proxy che permette la creazione di classi proxy dinamiche. In .NET per adesso manca un meccanismo così semplice. Ho trovato pubblicate 3-4 possibili soluzioni e quella che mi piace di più è con l'aiuto della classe NMock.Dynamic.ClassGenerator di NMock (in questo post di Joe Walnes - uno degli sviluppatori di NMock). Trovare il tempo per scriverne un articolo...
A giugno 2004, quindi la classifica è recentissima, 18 tra i primi 500 supercomputer più potenti del mondo si trovavano in Italia. I primi 3 appartengono all'ambiente universitario. Il primo occupa la posizione 63 in questa Top500 internazionale e la posizione 8 europea (dopo 4 supercomputer inglesi, 2 tedeschi e 1 francese). Una sorpresa (al meno per me) è che, di questi 18, Telecom ne ha ben 7!
CINECA (Consorzio Interuniversitario per il Calcolo Automatico dell'Italia Nord Orientale) (63, 159),
CILEA (Consorzio Interuniversitario Lombardo per l'Elaborazione Automatica) (209),
AGIP (Eni S.p.A) (237),
Manufacturing Company (Fiat?) (266),
Telecom Italia S.p.A (354, 355,...
Nel video di questo post su Channel 9, potete sentire al minuto 2:44, Stewart Tansley, PM Embedded Systems, Microsoft Research, che parla anche del team dell'Università di Pisa (Medialab R2D2 Team). Sono dei ragazzi fantastici e, anche se per molti di noi l'unico robot con cui interagiamo è il distributore di caffè :-) leggendo la loro DotNet mailing list possiamo trovare tante cose interessanti e di un interesse più largo. Per esempio, da un po' di tempo ho fatto subscribe al blog di Antonio Cisternino.
A differenza di Gaber (che adoro) ci sono momenti in cui io mi sento italiano ma per...
"The 'l' suffix is easily confused with the digit '1' -- use 'L' for clarity". Grazie a questo warning "premuroso" del compilatore C#, il seguente quiz in Java preso dalla stessa Session TS-2575 di 2004 JavaOne Conference non ha tanto senso in C#:
6. "It's Elementary"
public class Elementary{ public static void main(String[] args) { System.out.println(54321 + 5432l); }}
What Does It Print?
A. -22430
B. 59753
C. 10864
D. 108642Program doesn’t say what you think it does!
Another Look
public class Elementary{ public static void main(String[] args) { System.out.println(54321 + 5432l); }}
1 - the numeral one
l - the lowercase letter el
How Do You Fix It?
We won’t insult your intelligence
The Moral
Always...
Appena premuto il bottone "Inserici" per il post precedente, scopro un altro quiz (sempre della Session TS-2575 di 2004 JavaOne Conference presentata da Joshua Bloch e Neal Gafter) irriproducibile in C#: "5. Shades of Gray" (per essere precisi, l'autore in realtà è Dominik Gruntz e il quiz appare per la prima volta un anno e mezzo fa su Journal of Object Technology in un articolo interessante, intitolato "C# and Java: The Smart Distinctions").
Si tratta di un'altra "feature" di Java: "Java makes a distinction between the namespace of fields, methods and nested classes within a class, i.e., it is possible to...
Mi sono scaricato i 151 MB di PDF della "2004 JavaOne Conference" e ne stavo facendo un giro veloce quando ho trovato... che cosa? ...una session fatta solo di quiz :-)
J. Bloch, N. Gafter, "Still More Programming Puzzlers", Session TS-2575, 2004 JavaOne Conference
Il bello è che uno di questi quiz "4. More of the Same", è irriproducibile in C#! :-) Come mai? Perchè il quiz in questione sfrutta una "feature" di Java secondo la quale "It is possible for a method to have the same name as a constructor" ma, consigliano gli autori, "Don't ever do it". C# è nato...