Risipa de key_press | Programare

Programare .Net | Tehnici de programare | Tutoriale | Lectii si exemple

Risipa de key_press | Programare - Programare .Net | Tehnici de programare | Tutoriale | Lectii si exemple

Dynamic in C# 4.0

In cadrul lansarii .Net 4.0, una din temele principale a fost legata de programare dinamica. Tot atunci, a fost introdus cuvantul cheie dynamic in C#.
Un obiect este definit ca dinamic prin faptul ca structura si comportamentul lui nu sunt conforme cu un tip static (pe care compilatorul il recunoaste).
Exemple de obiecte dinamice sunt obiecte provenite din limbaje de programare dinamice ca Python sau Ruby, obiecte care isi schimba structura – HTML DOM – si altele.

C# este un limbaj type-safe. Acest lucru inseamna ca o variabila poate fi accesata doar prin tipul asociat, adica nu se poate interactiona cu o variabila de tip string ca si cum ar fi una de tip integer. Altfel spus, C# suporta static type checking (limbajul verifica type safety la momentul compilarii). Complementar, exista dynamic type safety ce are loc la runtime.

Un limbaj dinamic are proprietati opuse limbajului static. Tipul expresiei sau variabilei nu este cunoscut la momentul compilarii.

Observatie:

Dynamic type checking nu permite libertatea totala de a mixa tipurile pe motivul ca toate sunt la fel. Chiar folosind dynamic type checking, nu poti adauga o valoare Boolean la un Integer, de exemplu.

Chiar daca C# permite tipul dynamic, limbajul ramane static.

Tipul dynamic

Un tip dynamic este declarat prin cuvantul cheie dynamic.

            ////cream un obiect de tipul dynamic
            dynamic d = GetDynamicObject();
            //apelul metodei va avea loc la runtime
            d.Compute();

Tipul dynamic ii spune compilatorului sa nu intervina, sa nu faca verificarea. Programatorul stie ca, la runtime, obiectul d va avea metoda Compute. Bineinteles ca pentru a nu avea erori la compilare, metoda Compute trebuie sa fie implementata.
Cand o programator creeaza un tip dinamic, atunci nu il va interesa de unde provine, ca e din COM, sau ca e din IronPyton, HTML DOM, sau reflection. Programatorul doar va aplica operatiile pe care runtime-ul le va interpreta.

Campuri, proprietati, metode, evenimente, constructori, indecsi, operatori pot fi apelati dinamic.

            dynamic d =GetDynamicObject();
            //apel metoda
            d.Add();
            //propietati, campuri
            d.Name = d.FirstName;
            //indecsi
            d["Name"] = d["FirstName"];
            //constructor
            var c = new Person(d);

Conversii

Tipul dynamic poate fi privit ca un tip object. Orice object poate fi implicit convertit la dynamic. Invers, tipul dynamic poate fi convertit implicit la object sau la un alt tip, atat timp cat exista o conversie la runtime:

            //conversie implicita
            int i = 100;
            dynamic d = i;
            long j = d;

In codul de mai sus, conversia este implicita, pentru ca i este cuprins in j.

Urmatorul cod arunca exceptia RuntimeBinderException, pentru ca nu se poate face conversia implicit.

            int i = 100;
            dynamic d = i;
            short j = d;

Definim o metoda de tip dynamic, cu parametri de tip dynamic.

  public static class DynamicExample
    {
      public static dynamic InvokeDynamic(dynamic number)
      {
          return number + number ;
      }
    }

Putem apela acum aceasta metoda intr-un mod foarte interesant:

            string number = "10";
            DynamicExample.InvokeDynamic(number);
            int number = 10;
            DynamicExample.InvokeDynamic(number);
            double number = 10.45;
            DynamicExample.InvokeDynamic(number);

Dynamic vs. object

Definim o variabila de tip object.

            object o = 100;

Apelam metoda GetType pentru a vedea tipul variabilei. Vom primi raspuns ca este un Int32i, ceea ce este corect.

            Console.WriteLine(o.GetType());

Pentru urmatoarea instructiune vom primi eroare.

            o = o + 10;

Operator ‘+=’ cannot be applied to operands of type ‘object’ and ‘int’. A aparut pentru ca in momentul compilarii o este de tip object.

Solutia la care apelam, consta intr-o conversie (cast) la un Int32:

            o = (Int32)o + 10;

Aceasta solutie are dezavantajele ei. Daca facem o conversie gresita si in loc de Int32 scriem un String sau un Double, vom primi eroare la run-time: Unable to cast object of type ‘System.Int32’ to type ‘System.String’. Asadar, am facut o conversie explicita, dar la runtime aceasta conversie ar putea genera exceptie. Din momentul acesta, vom vedea cu ce ne poate ajuta tipul dynamic.

Tipul dynamic poate fi vazut ca o “versiune” a tipului object. Pentru problema expusa mai sus, tipul dynamic va “spune” compilatorului sa nu mai verifice tipurile.

            dynamic d = 100;
            Console.WriteLine(d.GetType());

Evident, este Int32.

Pentru urmatoare instructiune vom scapa de mesajul de eroare la compilare pentru ca datorita lui dynamic nu va mai avea loc type checking.

            d = d + 10;

Principala diferenta intre object si dynamic consta in incercarea compilatorului de a converti / a nu converti. In cazul dynamic compilatorul stie ca tipul unui obiect poate fi cunoscut doar la runtime si compilatorul nu incearca sa ii realizeze conversia, cum se intampla in cazul unui tip object.

Dynamic vs. var

Dupa explicatiile de mai sus, poate interveni intrebarea : Care este deosebirea dintre var si dynamic? Ambele infera tipurile in mod implicit.
In cazul var, compilatorul isi va da seama de tipuri, iar in cazul dynamic, runtime isi va da seama de tip.

            //tip dinamic, la runtime va fi string
            dynamic x = "abc";
            //tip string, la runtime va fi string
            var y = "abc";

            //eroare la runtime
            int i = x;
            //eroare la compilare
            int j = y;

Dynamic Language Runtime

In .Net 4.0 a aparut un run-time complementar, numit Dynamic Language Runtime (DLR). Acesta adauga un set de servicii in CLR, pentru limbajele dinamice. DLR permite o dezvoltare mai usoara cu limbajele dinamice si adauga functionalitati dinamice pentru limbajele statice. Scopul DLR este de a permite limbajelor dinamice sa ruleze pe .Net Framework si sa asigure interoperabilitate platformei.
O lista cu limbajele dinamice: Lisp, Smaltalk, Javascript, Php, Ruby, Python, ColdFusion, Lua, Cobra, Groovy.

Informatii mai multe despre DLR se gasesc pe msdn.

Exista situatii in care nu programatorul nu poate cunoaste tipul obiectului cu care lucreaza. Datele declarate ca dynamic nu sunt strongly type, nu sunt verificate la compilare, IntelliSense nu le detecteaza, dar utilizarea lor in unele circumstante poate rezolva problemele complexe in mod rapid. In plus, dynamic face codul mai usor de scris si de citit. C# 4.0 nu forteaza programatorul sa foloseasca tipul dynamic. El a fost introdus pentru a rezolva mai usor anumite scenarii.

Un exemplu clar despre ceea ce inseamna dynamic se poate gasi pe blog-ul lui Scott Hanselman:

Fara dynamic:

        object calc = GetCalculator();
        Type calcType = calc.GetType();
        object res = calcType.InvokeMember("Add", BindingFlags.InvokeMethod, null, new object[] { 10, 20 });
        int sum = Convert.ToInt32(res);

Cu dynamic:

        dynamic calc = GetCalculator();
        int sum = calc.Add(10, 20);
Category: Uncategorized

Your email address will not be published. Required fields are marked *

*