Avatar billede dresen Nybegynder
23. februar 2009 - 22:19 Der er 1 kommentar

Constraints in C# Generics + compile, load and runtime errors

Hej eksperter

Jeg 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
Avatar billede arne_v Ekspert
24. februar 2009 - 04:11 #1
compile time check og runtime check er ret åbenlyse

mit gæt på hvad han mener med load time check er følgende:

I.cs
----

namespace E
{
    public interface IX
    {
    }
}

Z1.cs
-----

namespace E
{
    public class Z : IX
    {
    }
}

Z2.cs
-----

namespace E
{
    public class Z
    {
    }
}

G.cs
----

using System;

namespace E
{
    public class G<T> where T : IX
    {
    }
    public class Program
    {
        public static void Main(string[] args)
        {
            G<Z> o = new G<Z>();
        }
    }
}

output
------

C:\>csc /t:library /out:I.dll I.cs
Microsoft (R) Visual C# 2008 Compiler version 3.5.30729.1
for Microsoft (R) .NET Framework version 3.5
Copyright (C) Microsoft Corporation. All rights reserved.


C:\>csc /r:I.dll /t:library /out:Z.dll Z1.cs
Microsoft (R) Visual C# 2008 Compiler version 3.5.30729.1
for Microsoft (R) .NET Framework version 3.5
Copyright (C) Microsoft Corporation. All rights reserved.


C:\>csc /r:I.dll /r:Z.dll G.cs
Microsoft (R) Visual C# 2008 Compiler version 3.5.30729.1
for Microsoft (R) .NET Framework version 3.5
Copyright (C) Microsoft Corporation. All rights reserved.


C:\>csc /r:I.dll /t:library /out:Z.dll Z2.cs
Microsoft (R) Visual C# 2008 Compiler version 3.5.30729.1
for Microsoft (R) .NET Framework version 3.5
Copyright (C) Microsoft Corporation. All rights reserved.


C:\>G

Unhandled Exception: System.TypeLoadException: GenericArguments[0], 'E.Z', on 'E.G`1[T]' violates the constraint of type parameter 'T'.
  at E.Program.Main(String[] args)
Avatar billede Ny bruger Nybegynder

Din løsning...

Tilladte BB-code-tags: [b]fed[/b] [i]kursiv[/i] [u]understreget[/u] Web- og emailadresser omdannes automatisk til links. Der sættes "nofollow" på alle links.

Loading billede Opret Preview
Kategori
IT-kurser om Microsoft 365, sikkerhed, personlig vækst, udvikling, digital markedsføring, grafisk design, SAP og forretningsanalyse.

Log ind eller opret profil

Hov!

For at kunne deltage på Computerworld Eksperten skal du være logget ind.

Det er heldigvis nemt at oprette en bruger: Det tager to minutter og du kan vælge at bruge enten e-mail, Facebook eller Google som login.

Du kan også logge ind via nedenstående tjenester