Operatori di test dei tipi ed espressioni di cast: is
, as
, typeof
e cast
Questi operatori ed espressioni eseguono il controllo del tipo o la conversione dei tipi. L'operatore is
controlla se il tipo di runtime di un'espressione è compatibile con un determinato tipo. L'operatore as
converte in modo esplicito un'espressione in un determinato tipo se il tipo di runtime è compatibile con tale tipo. Le espressioni di cast eseguono una conversione esplicita in un tipo di destinazione. L'operatore typeof
ottiene l'istanza System.Type per un tipo.
Operatore is
L' operatore is
controlla se il tipo di runtime del risultato di un'espressione è compatibile con un determinato tipo. L'operatore is
verifica anche un risultato dell'espressione rispetto a un criterio.
L'espressione con l'operatore di test del tipo is
ha il formato seguente:
E is T
in cui E
è un'espressione che restituisce un valore e T
è il nome di un tipo o un parametro di tipo. E
non può essere un metodo anonimo o un'espressione lambda.
L'operatore is
restituisce true
quando un risultato di un'espressione è non null e le condizioni seguenti sono vere:
Il tipo di runtime di un risultato dell'espressione è
T
.Il tipo di runtime di un risultato di un'espressione deriva dal tipo
T
, implementa l'interfacciaT
o esiste un'altra conversione di riferimento implicita da essa aT
.Il tipo di runtime di un risultato di un'espressione è un tipo valore nullable con il tipo sottostante
T
e Nullable<T>.HasValue ètrue
.Esiste una conversione boxing o unboxing dal tipo di run-time di un risultato di un'espressione al tipo
T
.
L'operatore is
non considera le conversioni definite dall'utente.
L'esempio seguente dimostra che l'operatore is
restituisce true
se il tipo di runtime del risultato di un'espressione deriva da un determinato tipo, ovvero se esiste una conversione di riferimento tra i tipi:
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
}
}
L'esempio successivo mostra che l'operatore is
prende in considerazione le conversioni boxing e unboxing ma non le conversioni numeriche:
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
Per informazioni sulle conversioni C#, vedere il capito Conversioni della specifica del linguaggio C#.
Test del tipo con criteri di ricerca
L'operatore is
verifica anche un risultato dell'espressione rispetto a un criterio. Nell'esempio seguente viene illustrato come usare un modello di dichiarazione per controllare il tipo di runtime di un'espressione:
int i = 23;
object iBoxed = i;
int? jNullable = 7;
if (iBoxed is int a && jNullable is int b)
{
Console.WriteLine(a + b); // output 30
}
Per informazioni sui modelli supportati, vedere Modelli.
Operatore as
L'operatore as
converte in modo esplicito il risultato di un'espressione in un tipo di valore nullable o di riferimento specificato. Se la conversione non è possibile, l'operatore as
restituisce null
. A differenza di un'espressione cast, l'operatore non genera mai un'eccezione as
.
Un'espressione nel formato
E as T
in cui E
è un'espressione che restituisce un valore e T
è il nome di un tipo o un parametro di tipo, produce lo stesso risultato di
E is T ? (T)(E) : (T)null
con la differenza che E
viene valutato una sola volta.
L'operatore as
considera solo conversioni di riferimenti, nullable, boxing e unboxing. Non è possibile usare l'operatore as
per eseguire una conversione definita dall'utente. A tale scopo, usare un'espressione cast.
Nell'esempio seguente viene illustrato l'uso dell'operatore as
:
IEnumerable<int> numbers = new List<int>(){10, 20, 30};
IList<int> indexable = numbers as IList<int>;
if (indexable != null)
{
Console.WriteLine(indexable[0] + indexable[indexable.Count - 1]); // output: 40
}
Nota
Come mostrato nell'esempio precedente, è necessario confrontare il risultato dell'espressione as
con null
per verificare se la conversione riesce. È possibile usare l'operatore is sia per verificare se la conversione ha esito positivo sia, se ha esito positivo, per assegnarne il risultato a una nuova variabile.
Espressione cast
Un'espressione cast nel formato (T)E
esegue una conversione esplicita del risultato dell'espressione E
nel tipo T
. Se non esiste alcuna conversione esplicita dal tipo E
al tipo T
, si verifica un errore in fase di compilazione. In fase di esecuzione, è possibile che una conversione esplicita non riesca e che un'espressione cast generi un'eccezione.
L'esempio seguente illustra conversioni esplicite numeriche e di riferimento:
double x = 1234.7;
int a = (int)x;
Console.WriteLine(a); // output: 1234
int[] ints = [10, 20, 30];
IEnumerable<int> numbers = ints;
IList<int> list = (IList<int>)numbers;
Console.WriteLine(list.Count); // output: 3
Console.WriteLine(list[1]); // output: 20
Per informazioni sulle conversioni esplicite supportate, vedere la sezione Conversioni esplicite della specifica del linguaggio C#. Per informazioni su come definire una conversione personalizzata del tipo esplicito o implicito, vedere Operatori di conversione definiti dall'utente.
Altri utilizzi di ()
È possibile usare le parentesi anche per chiamare un metodo oppure richiamare un delegato.
Le parentesi possono essere usate anche per specificare l'ordine in cui valutare le operazioni in un'espressione. Per altre informazioni, vedere Operatori C#.
Operatore typeof
L'operatore typeof
ottiene l'istanza System.Type per un tipo. L'argomento dell'operatore typeof
deve essere il nome o il parametro di un tipo, come illustrato nell'esempio seguente:
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]
L'argomento non deve essere un tipo che richiede annotazioni di metadati. Gli esempi includono i tipi seguenti:
dynamic
string?
(o qualsiasi tipo riferimento nullable)
Questi tipi non sono rappresentati direttamente nei metadati. I tipi includono attributi che descrivono il tipo sottostante. In entrambi i casi, è possibile usare il tipo sottostante. Anziché dynamic
, è possibile usare object
. Anziché string?
, è possibile usare string
.
È possibile usare l'operatore typeof
anche con tipi generici non associati. Il nome di un tipo generico non associato deve contenere il numero appropriato di virgole, ovvero una in meno rispetto al numero di parametri del tipo. L'esempio seguente illustra l'uso dell'operatore typeof
con un tipo generico non associato:
Console.WriteLine(typeof(Dictionary<,>));
// Output:
// System.Collections.Generic.Dictionary`2[TKey,TValue]
Un'espressione non può essere un argomento dell'operatore typeof
. Per ottenere l'istanza System.Type per il tipo di runtime del risultato dell'espressione, usare il metodo Object.GetType.
Test del tipo con l'operatore typeof
Usare l'operatore typeof
per controllare se il tipo di runtime del risultato dell'espressione corrisponde esattamente a un determinato tipo. L'esempio seguente illustra la differenza tra il controllo del tipo eseguito con l'operatore typeof
e il controllo del tipo con l'operatore 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
}
}
Overload degli operatori
Gli operatori is
, as
etypeof
non possono essere sottoposti a overload.
Un tipo definito dall'utente non può eseguire l'overload dell'operatore ()
, ma può definire conversioni di tipi personalizzate che possano essere eseguite da un'espressione cast. Per altre informazioni, vedere Operatori di conversione definiti dall'utente.
Specifiche del linguaggio C#
Per altre informazioni, vedere le sezioni seguenti delle specifiche del linguaggio C#: