CLS
Per tantissimi sarà ovvia ma la posto brevemente, solo come osservazione: implementare un'interfaccia non conforme al CLS con una classe conforme al CLS è possibile implementando esplicitamente i membri non conformi.
Questo codice, assolutamente simmetrico, l'ho scritto apposta per essere compilato sia in C# che in J#, senza modifiche:
// foo.txtclass Test{ static int i = 0; // J# entry point // vjc foo.txt public static void main(System.String[] args) { i++; System.Console.WriteLine(i); Main(args); } // C# entry point // csc foo.txt public static void Main(System.String[] args) { i++; System.Console.WriteLine(i); main(args); }}
Eseguendo il foo.exe, arriva la sorpresa: il numero di cicli che la variante J# riesce a fare (159830), supera il numero di cicli della variante C# (159781), fino al messaggio:
Process is terminated due to StackOverflowException.
Incuriosito da questa strana vittoria del...
Avere in un linguaggio .NET un metodo pubblico, non statico, conforme al CLS e di una classe pubblica, in un assembly, non necessariamente vuol dire che possa essere richiamato da un altro assembly!
L'esempio non è evidente: il metodo toString in questo snippet J#:
class A extends java.lang.Object{ public String toString() { return "A::toString"; }}
non può essere richiamato da C#:
class Test{ static void Main() { // error CS0117: 'A' does not contain a definition for 'toString' System.Console.WriteLine(new A().toString()); }}
se non lo sostituiamo con ToString. Da VisualBasic .NET invece, va ("identifiers are case insensitive"):
Class Test Shared Sub Main() ' OK ...
Il 23 di marzo, cioè tra meno di due settimane, presenterò una sessione al workshop RONUA (ROmanian .NET User Association) a Bucarest, alla sede di Microsoft Romania (grazie a Aurelian Popa per questo invito che mi onora). L'argomento sarà sempre CLS però il contenuto e la struttura rifatti completamente rispetto alla sessione presentata a dicembre, a Milano.
RONUA, da quando ve l'ho presentato l'autunno scorso, ha fatto delle belle cose: membro INETA, 5 workshop a Bucarest (questo del 23 sarà il sesto e al quarto sono venuti Jason Zander e Brandon Bynum) e 2 a Timisoara, 122 membri e ultimamente degli...
Chi ha seguito la mia sessione al workshop del 2 dicembre già lo conosce. Per gli altri, qui sotto, una domandina:
Cosa producono i seguenti due pezzi di codice?
C#
Visual Basic .NET
[IndexerName("P")] public string this[int i] { get { return _p[i]; } set { _p[i] = value; } }
<IndexerName("P")> _ Public Property Item(ByVal i As Integer) As String Get Return _p(i) End Get Set(ByVal Value As Integer) _p(i) = Value End Set End Property
Abbiamo visto nel post precedente come il compilatore Delphi crea una classe finta per ogni unit così che anche il codice procedurale soddisfi la regola CLS 36. Cosa succede invece quando non gli lasciamo più spazio agli trucchi e trasgrediamo in modo esplicito una regola CLS, per esempio la CLS Rule 11 (quella sulla signature)? Potremmo da C# "consumare" un codice come quello di seguito? (al tipo Word di Delphi corrisponde in C# il tipo ushort, non CLS)
// DelphiCls.paslibrary DelphiCls;usesFoo in 'Foo.pas';// inutile: Delphi non è CLS-compliant[assembly: CLSCompliant(True)]beginend.
// Foo.pasunit Foo;interface// non ha una signature conforme al CLSfunction BadArgType(i: Word): Word;implementationfunction...
Nel file "errors.h" che contiene la lista di tutti gli errori e warning del compilatore C# del Rotor c'è scritto che "Range 3000-3999 is reserved for CLS errors". Qui sotto nella tabella, ho mappato gli errori C# riguardanti esplicitamente il CLS alle regole del CLS trasgredite:
Visual C# Compiler Error / Warning Number
Rotor Error Name
Summary
Description
CLS Rule Number
CLS Rule
?
ERR_CLS_NoVarArgs
?
?
?
?
CS3001
ERR_CLS_BadArgType
Argument type 'type' is not CLS-compliant
A public, protected, or protected internal method must accept a parameter whose type is compliant with the CLS.
11
All types appearing in a signature shall be CLS-compliant. (p. 49 del PDF)
CS3002
ERR_CLS_BadReturnType
Return type of 'method' is not CLS-compliant
A public, protected, or...
Mi ha attirato l'attenzione un commento di Massimo Prota a questo post di Pierre. Beh, riguarda CLS, di cui vi parlerò giovedì - a sala vuota mi sa... :-)
Massimo segnalava in sostanza il fatto che in un assembly conforme al CLS non possiamo nominare gli identificatori dei campi protected con il prefisso "_" in una classe public.
Ne approfitto per aggiungere delle cose magari meno conosciute:
Beccare tra le 41 regole del CLS quella responsabile di questo vincolo non è immediato. Dovreste leggervi l'appendice 7 "Programming Language Identifiers" dell'"Unicode Technical Report #15" (come specificato dalla CLS Rule 4 - p. 44 del...
Il 2 di dicembre presenterò al workshop "Architecture & Management" una sessione su "CLS: regole per compilatori e per sviluppatori".
Inizio proprio in modo "potente" :-) visto che nell'altra sala ci sarà proprio Andrea... L'argomento che presento però mi piace da morire: è veramente poco conosciuto (ho guardato il webcast di Marco Russo "Ambiente object-oriented, CTS, CLS, FxCop" e la farò ben diversa) e in più è un argomento pieno-pieno di sorprese.
Ah, un'altra cosa: visto il mio accento straniero, cercherò di parlare in IL, così mi capirete tutti :-)