Constraints in C# Generics + compile, load and runtime errors
Hej eksperterJeg har læst dele af følgende artikel omkring Generics i C#: http://www.artima.com/intv/genericsP.html
Her forklarer Anders Hejlsberg bl.a., hvordan C# implementeringen af Generics muliggør, til forskel fra Java, at type informationer både eksisterer på kompilerings- og kørselstidspunktet.
I teksten omtaler Hejlsberg "constraints in C# Generics" optræder som en underoverskrift i teksten), og forklarer hvordan der kan udtrykkes constraints for type parameters, og herunder hvilke fordele dette giver.
Blandt de fordele der nævnes optræder følgende: "With a constraint, you can hoist that dynamic check out of your code and have it be verifiable at compile time or load time".
Jeg har tidligere kun kendt til compile og runtime checks, og aldrig hørt om at CLR udfører checks på load tidspunktet. Det har motiveret, at jeg vil prøve at få en bedre forståelse af, hvordan check udføres og evt. fejl opdages i forbindelse hhv. compile, load og runtime checking.
Det er mit håb at I kan hjælpe mig til en bedre forståelse. Nedenfor optræder kodeeksempler med relaterede spørgsmål, som jeg tænker kan danne grundlag for diskussion.
------------------------------
Eks-kode
public class MyDict <K,V> where K : IComparable
{
Add(K key, V value)
{
key.ComparaTo(...);
}
}
class SomeTypeNotComparable
{}
class SomeTypeComparable: IComparable
{
int ComparaTo()
{
.....
}
}
* 1) Compile time fejl
------------------------------
Følgende kodelinie bør fører til en kompile time fejl:
- MyDict<SomeTypeNotComparable, String> aDict = new MyDict<SomeTypeNotComparable>();
Så vidt jeg har forstået, så gør kompileren brug af metadata, til at finde detaljeinformationer omkring de typer som optræder i programmet.
- Hvordan dette præcis foregår er jeg dog ikke vidende om - nogen der kan hjælpe?
Det må skulle foregå i en bestemt sekvens, så der foreligger metadata for de typer, som der sidenhen bliver referert til af andre typer.
I ovenstående eksempel, skal der altså foreligge metadata for SomeTypeNotComparable, førend linien "key.CompareTo(...)" behandles af compileren.
- Har det at gøre med rækkefølgen for fortolkning af et syntaks-træ, eller roder jeg rundt i tingene?
Ved at bruge værktøjet "IL Dasm", kan jeg se følgende metadata for hhv. SomeTypeNotComparable og SomeTypeComparable. Det fremgår her at typen SomeTypeComprable implementerer interface System.IComparable og at dette interface er eksternt til det assembly, som typen SomeTypeComparable optræder i (jf. [TypeRef]):
TypeDef #4 (02000005)
-------------------------------------------------------
TypDefName: HejlsbergGenericsConstraints.SomeTypeNotComparable (02000005)
Flags : [NotPublic] [AutoLayout] [Class] [AnsiClass] [BeforeFieldInit] (00100000)
Extends : 01000001 [TypeRef] System.Object
Method #1 (06000007)
-------------------------------------------------------
MethodName: .ctor (06000007)
Flags : [Public] [HideBySig] [ReuseSlot] [SpecialName] [RTSpecialName] [.ctor] (00001886)
RVA : 0x0000213a
ImplFlags : [IL] [Managed] (00000000)
CallCnvntn: [DEFAULT]
hasThis
ReturnType: Void
No arguments.
TypeDef #5 (02000006)
-------------------------------------------------------
TypDefName: HejlsbergGenericsConstraints.SomeTypeComparable (02000006)
Flags : [NotPublic] [AutoLayout] [Class] [AnsiClass] [BeforeFieldInit] (00100000)
Extends : 01000001 [TypeRef] System.Object
Method #1 (06000008)
-------------------------------------------------------
MethodName: CompareTo (06000008)
Flags : [Public] [Final] [Virtual] [HideBySig] [NewSlot] (000001e6)
RVA : 0x00002144
ImplFlags : [IL] [Managed] (00000000)
CallCnvntn: [DEFAULT]
hasThis
ReturnType: I4
1 Arguments
Argument #1: Object
1 Parameters
(1) ParamToken : (08000006) Name : obj flags: [none] (00000000)
Method #2 (06000009)
-------------------------------------------------------
MethodName: .ctor (06000009)
Flags : [Public] [HideBySig] [ReuseSlot] [SpecialName] [RTSpecialName] [.ctor] (00001886)
RVA : 0x00002157
ImplFlags : [IL] [Managed] (00000000)
CallCnvntn: [DEFAULT]
hasThis
ReturnType: Void
No arguments.
InterfaceImpl #1 (09000001)
-------------------------------------------------------
Class : HejlsbergGenericsConstraints.SomeTypeComparable
Token : 01000002 [TypeRef] System.IComparable
* 2) Run time fejl
------------------------------
public class MyDict<K,V>{
{
Add(K key, V value)
{
IComparable keyComparer = (IComparable) key;
keyComparer.ComparaTo(...);
}
}
Lad os antage at der ikke blev angivet et eksplicit constraint for den generelle type K. Der optræder tilgengæld et implicit constraint i og med, at
typen K, som optræder i den formelle parameter i metoden Add type castes til typen IComparable. Dette med henblik på at kalde metoden CompareTo.
Kaldes metoden Add med en type som første argument, der ikke implementerer interfacet Icomparable (f.eks.: Add(new SomeTypeNotComparable()...)),
da opstår en exception af typen System.InvalidCastException.
- Jeg vil mene at dette foregår run time (er som sagt ikke sikker på forskellen mellem run time og load time). Jeg er en konceptuel forståelse af, hvad der ligger til grund for fejlens opståen. Er der nogen der kan forklare mig, hvordan fejlen "detectes" i praksis?
* 3) Load time fejl
------------------------------
- Er der en der kan forklare dette - evt. med et kodeeksempel baseret på ovenstående kode?.
På forhånd tak for hjælpen :]
vh/ dresen