Używanie dynamicznego typu
Typ dynamic
jest typem statycznym, ale obiekt typu dynamic
pomija sprawdzanie typu statycznego. W większości przypadków działa tak, jakby miał typ object
. Kompilator zakłada, że element obsługuje dowolną dynamic
operację. W związku z tym nie musisz określać, czy obiekt pobiera jego wartość z interfejsu API COM, z języka dynamicznego, takiego jak IronPython, z modelu DOM (DOCUMENT Object Model), odbicia lub z innego miejsca w programie. Jeśli jednak kod nie jest prawidłowy, błędy pojawią się w czasie wykonywania.
Jeśli na przykład metoda exampleMethod1
wystąpienia w poniższym kodzie ma tylko jeden parametr, kompilator rozpoznaje, że pierwsze wywołanie metody , nie jest prawidłowe, ec.exampleMethod1(10, 4)
ponieważ zawiera dwa argumenty. Wywołanie powoduje błąd kompilatora. Kompilator nie sprawdza drugiego wywołania metody , dynamic_ec.exampleMethod1(10, 4)
ponieważ typ dynamic_ec
to dynamic
. W związku z tym nie jest zgłaszany żaden błąd kompilatora. Jednak błąd nie jest zwracany w nieskończoność. Pojawia się on w czasie wykonywania i powoduje wyjątek czasu wykonywania.
static void Main(string[] args)
{
ExampleClass ec = new ExampleClass();
// The following call to exampleMethod1 causes a compiler error
// if exampleMethod1 has only one parameter. Uncomment the line
// to see the error.
//ec.exampleMethod1(10, 4);
dynamic dynamic_ec = new ExampleClass();
// The following line is not identified as an error by the
// compiler, but it causes a run-time exception.
dynamic_ec.exampleMethod1(10, 4);
// The following calls also do not cause compiler errors, whether
// appropriate methods exist or not.
dynamic_ec.someMethod("some argument", 7, null);
dynamic_ec.nonexistentMethod();
}
class ExampleClass
{
public ExampleClass() { }
public ExampleClass(int v) { }
public void exampleMethod1(int i) { }
public void exampleMethod2(string str) { }
}
Rolą kompilatora w tych przykładach jest spakowanie razem informacji o tym, co każda instrukcja proponuje zrobić dla dynamic
obiektu lub wyrażenia. Środowisko uruchomieniowe sprawdza przechowywane informacje i dowolną instrukcję, która nie jest prawidłowa, powoduje wyjątek czasu wykonywania.
Wynikiem najbardziej dynamicznych operacji jest sam dynamic
. Jeśli na przykład wskaźnik myszy testSum
zostanie użyty w poniższym przykładzie, funkcja IntelliSense wyświetli test dynamiczny typu (zmienna lokalna).
dynamic d = 1;
var testSum = d + 3;
// Rest the mouse pointer over testSum in the following statement.
System.Console.WriteLine(testSum);
Operacje, w których wynik nie dynamic
obejmuje:
- Konwersje z
dynamic
na inny typ. - Wywołania konstruktora, które zawierają argumenty typu
dynamic
.
Na przykład typ testInstance
w następującej deklaracji to ExampleClass
, a nie dynamic
:
var testInstance = new ExampleClass(d);
Konwersje
Konwersje między obiektami dynamicznymi i innymi typami są łatwe. Konwersje umożliwiają deweloperowi przełączanie się między zachowaniem dynamicznym i niedynamicznym.
Dowolny można przekonwertować na dynamic
niejawnie, jak pokazano w poniższych przykładach.
dynamic d1 = 7;
dynamic d2 = "a string";
dynamic d3 = System.DateTime.Today;
dynamic d4 = System.Diagnostics.Process.GetProcesses();
Z drugiej strony można dynamicznie stosować dowolną niejawną konwersję do dowolnego wyrażenia typu dynamic
.
int i = d1;
string str = d2;
DateTime dt = d3;
System.Diagnostics.Process[] procs = d4;
Rozpoznawanie przeciążenia z argumentami typu dynamicznego
Rozpoznawanie przeciążeń występuje w czasie wykonywania zamiast w czasie kompilacji, jeśli co najmniej jeden argument w wywołaniu metody ma typ dynamic
, lub jeśli odbiornik wywołania metody jest typu dynamic
. W poniższym przykładzie, jeśli jedyna dostępna exampleMethod2
metoda przyjmuje argument ciągu, wysyłanie d1
jako argument nie powoduje błędu kompilatora, ale powoduje wyjątek czasu wykonywania. Rozpoznawanie przeciążenia kończy się niepowodzeniem w czasie wykonywania, ponieważ typ d1
czasu wykonywania to int
, i exampleMethod2
wymaga ciągu.
// Valid.
ec.exampleMethod2("a string");
// The following statement does not cause a compiler error, even though ec is not
// dynamic. A run-time exception is raised because the run-time type of d1 is int.
ec.exampleMethod2(d1);
// The following statement does cause a compiler error.
//ec.exampleMethod2(7);
Środowisko uruchomieniowe języka dynamicznego
Środowisko uruchomieniowe języka dynamicznego (DLR) udostępnia infrastrukturę, która obsługuje dynamic
typ języka C#, a także implementację języków programowania dynamicznego, takich jak IronPython i IronRuby. Aby uzyskać więcej informacji na temat biblioteki DLR, zobacz Dynamic Language Runtime Overview (Omówienie środowiska uruchomieniowego języka dynamicznego).
COM interop
Wiele metod COM umożliwia zmianę typów argumentów i zwracanie typu przez wyznaczenie typów jako object
. Międzyoperacyjna com wymaga jawnego rzutowania wartości w celu koordynowania z silnie typinymi zmiennymi w języku C#. Jeśli kompilujesz przy użyciu opcji EmbedInteropTypes (opcje kompilatora języka C#), wprowadzenie dynamic
typu umożliwia traktowanie wystąpień object
w podpisach COM tak, jakby były typu dynamic
, a tym samym uniknąć dużej części rzutowania. Aby uzyskać więcej informacji na temat używania dynamic
typu z obiektami COM, zobacz artykuł How to access Office interop objects by using C# features (Jak uzyskać dostęp do obiektów międzyoperacyjnych pakietu Office przy użyciu funkcji języka C#).
Powiązane artykuły
Nazwa | opis |
---|---|
dynamic | Opisuje użycie słowa kluczowego dynamic . |
Przegląd środowiska uruchomieniowego języka dynamicznego | Zawiera omówienie biblioteki DLR, czyli środowiska uruchomieniowego, które dodaje zestaw usług dla języków dynamicznych do środowiska uruchomieniowego języka wspólnego (CLR). |
Przewodnik: tworzenie i używanie obiektów dynamicznych | Zawiera instrukcje krok po kroku dotyczące tworzenia niestandardowego obiektu dynamicznego oraz tworzenia projektu, który uzyskuje IronPython dostęp do biblioteki. |