dynamic - Typy dynamiczne w języku C#

Typ dynamic - zmiana typu zmiennej w czasie działania programu.


W C# 4.0 został wprowadzony nowy typ danych - dynamic. Dzięki wprowadzeniu typów dynamicznych możemy w trakcie działania programu zmieniać typ danych zapisanych w zmiennych. Statyczne typykompilowane poprzez środowisko uruchomieniowe CLR (Common Language Runtime). Typy dynamiczne są omijane przez kompilator CLR, przechwytywane przez środowisko uruchomieniowe DLR (Dynamic Language Runtime) i obsługiwane w czasie działania programu. DLR jest częścią CLR, powstało aby umożliwić współprace z dynamicznymi językami. Język C# jest ściśle typowany, wszystkie zmienne muszą mieć swój typ przed uruchomieniem programu a więc w trakcie kompilacji. Języki dynamicznie typowane (PHP, Ruby, Python) nie wymagają przypisywania typów do zmiennych. Typ zmiennej wynika z wartości jaką przechowuje i jest sprawdzany w czasie działania programu. Kod języka dynamicznie typowanego nie wymaga od programisty obowiązku deklarowania typu zmiennych jednak jest trudniejszy do analizy w razie wystąpienia błędów.

Przykładowy kod z użyciem słowa kluczowego dynamic:

public class Program
{
    public static void Main()
    {
        dynamic d = 13;
        Console.WriteLine(d.GetType());
        //Typ zmiennej d to: System.Int32
 
        d = "Napis";
        //Teraz typ zmiennej d to: Systems.String
 
        d--;    //BŁĄD zmienna jest aktualnie typu String

        Console.ReadLine();
    }
}
W powyższym kodzie zwróciliśmy uwagę na słabe strony typowania dynamicznego. W przypadku typowania statycznego instrukcja d-- zostałaby automatycznie podkreślona przez kompilator, natomiast w przypadku typowania dynamicznego kompilator ją opuszcza i jest ona sprawdzana dopiero w czasie działania programu.

Dynamic, var, object - porównanie

Słowa kluczowe var oraz object, również pozwalają na przechowywanie zmiennych różnych typów.
Typ var przypisuje typ do zmiennej na podstawie danych, którymi ją zainicjujemy a więc, zmienna jest kompilowana i sprawdzana przez kompilator w czasie pisania programu. Nie ma możliwości późniejszej zmiany typu dla zmiennej.
var zmienna = 10;
Console.WriteLine(zmienna.GetType());
//wyświetli System.Int32
 
zmienna = "napis"; // BŁĄD zmienna jest typu int
Typ object jest typem po którym dziedziczą wszystkie inne typy, pozwala na przypisanie zmiennych dowolnych typów jednak podczas działań na zmiennej typu object musimy wykonać rzutowanie na konkretny typ.
object zmienna = 10;
Console.WriteLine(zmienna.GetType());
//wyświetli System.Int32
 
zmienna  = (int)zmienna + 1;  //rzutowanie
 
zmienna = "napis"; // OK
Console.WriteLine(zmienna.GetType());
//wyświetli System.String
Typ object jest najbardziej zbliżony do typu dynamic jednak mają pewną różnicę. W przypadku typu object nie możemy korzystać z właściwości zadeklarowanych dla zmiennych danego typu, ponieważ kompilator traktuje je jak zmienne typu object. W przypadku zmiennych dynamicznych typ podczas działania na zmiennej jest już znany a więc można wykorzystać jego właściwości.
object zmienna = "napis";
Console.WriteLine(zmienna.Length);
//błąd typ object nie posiada właściwości Lenght
 
dynamic zmienna1 = "napis"; 
Console.WriteLine(zmienna1.Length);
// OK wyświetli długość zmiennej czyli: 5 

Zmienne dynamiczne a wydajność

Aby sprawdzić wydajność zmiennych dynamicznych wykorzystamy następujący kod:
public class Program
{
    private static void TestDynamicznych()
    {
        var stopwatch = Stopwatch.StartNew();
 
        dynamic a = 10;
        dynamic b = 20;
        dynamic c = 30;
 
        dynamic d = a + b + c;
 
        stopwatch.Stop();
        Console.WriteLine("Czas zmiennych dynamicznych:{0}", stopwatch.ElapsedTicks);
    }
 
    private static void TestStatycznych()
    {
        var stopwatch = Stopwatch.StartNew();
 
        int a = 10;
        int b = 20;
        int c = 30;
 
        int d = a + b + c;
 
        stopwatch.Stop();
        Console.WriteLine("Czas zmiennych statycznych:{0}", stopwatch.ElapsedTicks);
    }
 
    public static void Main()
    {
        TestDynamicznych();
        TestStatycznych();
        TestDynamicznych();
        TestStatycznych();
        TestDynamicznych();
        TestStatycznych();
        TestDynamicznych();
        TestStatycznych();
        Console.ReadLine();
    }
}

Wynik działania programu:

Czas zmiennych dynamicznych:82481
Czas zmiennych statycznych:1
Czas zmiennych dynamicznych:5
Czas zmiennych statycznych:1
Czas zmiennych dynamicznych:4
Czas zmiennych statycznych:1
Czas zmiennych dynamicznych:5
Czas zmiennych statycznych:1

Pierwsze wywołanie metody ze zmiennymi dynamicznymi było aż 82tyś. razy wolniejsze niż ta sama metoda ze zmiennymi typowanymi statycznie. Kolejne wywołania były ok 5 razy wolniejsze niż na zmiennych statycznych. W przypadku zmiennych statycznych typy były znane jeszcze przed uruchomieniem programu, ponieważ była uruchomiona kompilacja programu. Dla zmiennych dynamicznych typy były wyznaczane podczas działania programu, dlatego trwało to dużo dłużej. Ponieważ kompilator DLR sprawdza na początku czy metoda nie została już wcześniej skompilowana kolejne wywołania metody są dużo szybsze, jednak nie tak szybkie jak przy zmiennych typowanych statycznie.
Komentarze facebook (polub nasz profil na FB aby je zobaczyć):