Operatory testowania typów i wyrażenie rzutowania (odwołanie w C#)

Do sprawdzania typów lub konwersji typów można użyć następujących operatorów i wyrażeń:

is, operator

Operator sprawdza, czy typ czasu uruchomienia wyniku wyrażenia is jest zgodny z danym typem. Począwszy od języka C# 7.0, operator testuje również is wynik wyrażenia względem wzorca.

Wyrażenie z operatorem testowania typów is ma następującą postać

E is T

gdzie E to wyrażenie, które zwraca wartość i T jest nazwą typu lub parametru typu. E nie może być metodą anonimową ani wyrażeniem lambda.

Operator is zwraca wartość , gdy wynik wyrażenia ma wartość true niezerową i dowolny z następujących warunków jest prawdziwy:

  • Typ czasu uruchamiania wyniku wyrażenia to T .

  • Typ czasu wykonania wyniku wyrażenia pochodzi z typu T , implementuje interfejs T lub istnieje inna niejawna konwersja odwołania do . T

  • Typ czasu uruchomieniowego wyniku wyrażenia jest typem wartości dopuszczania wartości null z typem bazowym, a T typ to Nullable<T>.HasValue true .

  • Konwersja konwersji boxing lub unboxing istnieje z typu w czasie uruchomieniowym wyniku wyrażenia na typ T .

Operator is nie uwzględnia konwersji zdefiniowanych przez użytkownika.

W poniższym przykładzie pokazano, że operator zwraca wartość , jeśli typ w czasie działania wyniku wyrażenia pochodzi z danego typu, to oznacza to, że istnieje konwersja odwołania is true między typami:

public class Base { }

public class Derived : Base { }

public static class IsOperatorExample
{
    public static void Main()
    {
        object b = new Base();
        Console.WriteLine(b is Base);  // output: True
        Console.WriteLine(b is Derived);  // output: False

        object d = new Derived();
        Console.WriteLine(d is Base);  // output: True
        Console.WriteLine(d is Derived); // output: True
    }
}

W następnym przykładzie pokazano, że operator uwzględnia konwersje boxing i unboxing, ale nie is uwzględnia konwersji liczbowych:

int i = 27;
Console.WriteLine(i is System.IFormattable);  // output: True

object iBoxed = i;
Console.WriteLine(iBoxed is int);  // output: True
Console.WriteLine(iBoxed is long);  // output: False

Aby uzyskać informacje na temat konwersji języka C#, zobacz rozdział Conversions (Konwersje) specyfikacji języka C#.

Testowanie typów za pomocą dopasowywania do wzorca

Począwszy od języka C# 7.0, operator testuje również is wynik wyrażenia względem wzorca. W poniższym przykładzie pokazano, jak używać wzorca deklaracji do sprawdzania typu w czasie działania wyrażenia:

int i = 23;
object iBoxed = i;
int? jNullable = 7;
if (iBoxed is int a && jNullable is int b)
{
    Console.WriteLine(a + b);  // output 30
}

Aby uzyskać informacje o obsługiwanych wzorcach, zobacz Patterns (Wzorce).

operator as

Operator jawnie konwertuje wynik wyrażenia na dane odwołanie lub typ wartości as dopuszczania wartości null. Jeśli konwersja nie jest możliwa, as operator zwraca wartość null . W przeciwieństwie do wyrażenia rzutowania as operator nigdy nie zgłasza wyjątku.

Wyrażenie formularza

E as T

gdzie to wyrażenie, które zwraca wartość i jest nazwą typu lub parametru typu, generuje E ten sam wynik T co

E is T ? (T)(E) : (T)null

z tą E różnicą, że wartość jest oceniana tylko raz.

Operator as uwzględnia tylko konwersje odwołania, konwersje dopuszczające wartość null, konwersje boxing i konwersje rozpakowania. Nie można użyć operatora as do wykonania konwersji zdefiniowanej przez użytkownika. Aby to zrobić, użyj wyrażenia rzutowania.

W poniższym przykładzie pokazano użycie as operatora :

IEnumerable<int> numbers = new[] { 10, 20, 30 };
IList<int> indexable = numbers as IList<int>;
if (indexable != null)
{
    Console.WriteLine(indexable[0] + indexable[indexable.Count - 1]);  // output: 40
}

Uwaga

Jak pokazano w poprzednim przykładzie, należy porównać wynik wyrażenia z wartością , aby sprawdzić, as null czy konwersja zakończyła się pomyślnie. Począwszy od języka C# 7.0, można użyć operatora is zarówno do testowania, czy konwersja powiedzie się, a jeśli się powiedzie, przypisać jej wynik do nowej zmiennej.

Wyrażenie rzutowania

Wyrażenie rzutowania formularza wykonuje (T)E jawną konwersję wyniku wyrażenia E na typ T . Jeśli nie istnieje jawna konwersja typu E na typ , wystąpi błąd w czasie T kompilacji. W czasie rzeczywistym jawna konwersja może nie powieść się, a wyrażenie rzutowania może zgłosić wyjątek.

W poniższym przykładzie przedstawiono jawne konwersje liczbowe i referencyjne:

double x = 1234.7;
int a = (int)x;
Console.WriteLine(a);   // output: 1234

IEnumerable<int> numbers = new int[] { 10, 20, 30 };
IList<int> list = (IList<int>)numbers;
Console.WriteLine(list.Count);  // output: 3
Console.WriteLine(list[1]);  // output: 20

Aby uzyskać informacje o obsługiwanych konwersjach jawnych, zobacz sekcję Konwersje jawne w specyfikacji języka C#. Aby uzyskać informacje na temat sposobu definiowania niestandardowej jawnej lub niejawnej konwersji typu, zobacz Operatorykonwersji zdefiniowane przez użytkownika .

Inne zastosowania ()

Nawiasy są również służące do wywoływania metody lub wywoływania delegata.

Innym zastosowaniem nawiasów jest dostosowanie kolejności oceniania operacji w wyrażeniu. Aby uzyskać więcej informacji, zobacz Operatory języka C#.

typeof — Operator

Operator typeof uzyskuje wystąpienie dla System.Type typu. Argumentem operatora musi być nazwa typu lub typeof parametru typu, jak pokazano w poniższym przykładzie:

void PrintType<T>() => Console.WriteLine(typeof(T));

Console.WriteLine(typeof(List<string>));
PrintType<int>();
PrintType<System.Int32>();
PrintType<Dictionary<int, char>>();
// Output:
// System.Collections.Generic.List`1[System.String]
// System.Int32
// System.Int32
// System.Collections.Generic.Dictionary`2[System.Int32,System.Char]

Argument nie może być typem, który wymaga adnotacji metadanych. Przykłady obejmują następujące typy:

  • dynamic
  • string? (lub dowolny typ referencyjny dopuszczany wartością null)

Te typy nie są bezpośrednio reprezentowane w metadanych. Typy obejmują atrybuty, które opisują typ podstawowy. W obu przypadkach można użyć typu bazowego. Zamiast dynamic , można użyć . object Zamiast string? , można użyć . string

Można również użyć operatora typeof z niepowiązanych typów ogólnych. Nazwa niezwiązanego typu ogólnego musi zawierać odpowiednią liczbę przecinków, która jest mniejsza niż liczba parametrów typu. W poniższym przykładzie pokazano użycie typeof operatora z niepowiązanym typem ogólnym:

Console.WriteLine(typeof(Dictionary<,>));
// Output:
// System.Collections.Generic.Dictionary`2[TKey,TValue]

Wyrażenie nie może być argumentem typeof operatora. Aby uzyskać wystąpienie dla typu czasu działania wyniku System.Type wyrażenia, użyj Object.GetType metody .

Testowanie typów za pomocą typeof operatora

Użyj operatora , aby sprawdzić, czy typ czasu uruchomienia wyniku wyrażenia dokładnie pasuje typeof do danego typu. W poniższym przykładzie pokazano różnicę między sprawdzaniem typów wykonywane za pomocą typeof operatora a operatorem is:

public class Animal { }

public class Giraffe : Animal { }

public static class TypeOfExample
{
    public static void Main()
    {
        object b = new Giraffe();
        Console.WriteLine(b is Animal);  // output: True
        Console.WriteLine(b.GetType() == typeof(Animal));  // output: False

        Console.WriteLine(b is Giraffe);  // output: True
        Console.WriteLine(b.GetType() == typeof(Giraffe));  // output: True
    }
}

Przeciążanie operatorów

Operatory is , i nie mogą być as typeof przeciążone.

Typ zdefiniowany przez użytkownika nie może przeciążyć operatora, ale może definiować niestandardowe konwersje typów, które mogą być () wykonywane przez wyrażenie rzutowania. Aby uzyskać więcej informacji, zobacz User-defined conversion operators (Operatory konwersji zdefiniowane przez użytkownika).

specyfikacja języka C#

Aby uzyskać więcej informacji, zobacz następujące sekcje specyfikacji języka C#:

Zobacz też