ConversioniConversions

Una conversione consente a un'espressione di essere considerata come un tipo particolare.A conversion enables an expression to be treated as being of a particular type. Una conversione può causare che un'espressione di un tipo specificato venga considerata come avente un tipo diverso oppure può causare un'espressione senza un tipo per ottenere un tipo.A conversion may cause an expression of a given type to be treated as having a different type, or it may cause an expression without a type to get a type. Le conversioni possono essere implicite o esplicitee determinare se è necessario un cast esplicito.Conversions can be implicit or explicit, and this determines whether an explicit cast is required. Ad esempio, la conversione dal tipo int al tipo long è implicita, quindi le espressioni di tipo int possono essere considerate in modo implicito come tipo long.For instance, the conversion from type int to type long is implicit, so expressions of type int can implicitly be treated as type long. La conversione opposta, dal tipo long al tipo int, è esplicita ed è quindi necessario un cast esplicito.The opposite conversion, from type long to type int, is explicit and so an explicit cast is required.

int a = 123;
long b = a;         // implicit conversion from int to long
int c = (int) b;    // explicit conversion from long to int

Alcune conversioni sono definite dal linguaggio.Some conversions are defined by the language. I programmi possono anche definire conversioni personalizzate (conversioni definite dall'utente).Programs may also define their own conversions (User-defined conversions).

Conversioni impliciteImplicit conversions

Le conversioni seguenti sono classificate come conversioni implicite:The following conversions are classified as implicit conversions:

  • Conversioni di identitàIdentity conversions
  • Conversioni numeriche impliciteImplicit numeric conversions
  • Conversioni di enumerazione impliciteImplicit enumeration conversions
  • Conversioni implicite di stringhe interpolateImplicit interpolated string conversions
  • Conversioni implicite NullableImplicit nullable conversions
  • Conversioni di valori letterali nullNull literal conversions
  • Conversioni di riferimenti impliciteImplicit reference conversions
  • Conversioni boxingBoxing conversions
  • Conversioni dinamiche impliciteImplicit dynamic conversions
  • Conversioni implicite di espressioni costantiImplicit constant expression conversions
  • Conversioni implicite definite dall'utenteUser-defined implicit conversions
  • Conversioni di funzioni anonimeAnonymous function conversions
  • Conversioni di gruppi di metodiMethod group conversions

Le conversioni implicite possono verificarsi in varie situazioni, incluse le chiamate ai membri della funzione (controllo della fase di compilazione della risoluzione dell'overload dinamico), le espressioni cast (espressioni cast) e le assegnazioni (operatori di assegnazione).Implicit conversions can occur in a variety of situations, including function member invocations (Compile-time checking of dynamic overload resolution), cast expressions (Cast expressions), and assignments (Assignment operators).

Le conversioni implicite predefinite hanno sempre esito positivo e non generano mai eccezioni.The pre-defined implicit conversions always succeed and never cause exceptions to be thrown. Le conversioni implicite definite dall'utente progettate correttamente devono presentare anche queste caratteristiche.Properly designed user-defined implicit conversions should exhibit these characteristics as well.

Ai fini della conversione, i tipi object e dynamic sono considerati equivalenti.For the purposes of conversion, the types object and dynamic are considered equivalent.

Tuttavia, le conversioni dinamiche (le conversioni dinamicheimplicite e le conversioni dinamiche esplicite) si applicano solo alle espressioni di tipo dynamic (il tipo dinamico).However, dynamic conversions (Implicit dynamic conversions and Explicit dynamic conversions) apply only to expressions of type dynamic (The dynamic type).

Conversione di identitàIdentity conversion

Una conversione di identità converte da qualsiasi tipo nello stesso tipo.An identity conversion converts from any type to the same type. Questa conversione esiste in modo che un'entità che dispone già di un tipo obbligatorio possa essere convertita in tale tipo.This conversion exists such that an entity that already has a required type can be said to be convertible to that type.

  • Poiché object e dynamic sono considerati equivalenti, esiste una conversione di identità tra object e dynamice tra tipi costruiti identici quando si sostituiscono tutte le occorrenze di dynamic con object.Because object and dynamic are considered equivalent there is an identity conversion between object and dynamic, and between constructed types that are the same when replacing all occurrences of dynamic with object.

Conversioni numeriche impliciteImplicit numeric conversions

Le conversioni numeriche implicite sono:The implicit numeric conversions are:

  • Da sbyte a short, int, long, float, doubleo decimal.From sbyte to short, int, long, float, double, or decimal.
  • Da byte a short, ushort, int, uint, long, ulong, float, doubleo decimal.From byte to short, ushort, int, uint, long, ulong, float, double, or decimal.
  • Da short a int, long, float, doubleo decimal.From short to int, long, float, double, or decimal.
  • Da ushort a int, uint, long, ulong, float, doubleo decimal.From ushort to int, uint, long, ulong, float, double, or decimal.
  • Da int a long, float, doubleo decimal.From int to long, float, double, or decimal.
  • Da uint a long, ulong, float, doubleo decimal.From uint to long, ulong, float, double, or decimal.
  • Da long a float, doubleo decimal.From long to float, double, or decimal.
  • Da ulong a float, doubleo decimal.From ulong to float, double, or decimal.
  • Da char a ushort, int, uint, long, ulong, float, doubleo decimal.From char to ushort, int, uint, long, ulong, float, double, or decimal.
  • Da float a double.From float to double.

Le conversioni da int, uint, longo ulong a float e da long o ulong a double possono causare una perdita di precisione, ma non provocheranno mai una perdita di grandezza.Conversions from int, uint, long, or ulong to float and from long or ulong to double may cause a loss of precision, but will never cause a loss of magnitude. Le altre conversioni numeriche implicite non perdono mai le informazioni.The other implicit numeric conversions never lose any information.

Non esistono conversioni implicite al tipo char, pertanto i valori degli altri tipi integrali non vengono convertiti automaticamente nel tipo di char.There are no implicit conversions to the char type, so values of the other integral types do not automatically convert to the char type.

Conversioni di enumerazione impliciteImplicit enumeration conversions

Una conversione di enumerazione implicita consente di convertire il decimal_integer_literal 0 in qualsiasi enum_type e in qualsiasi nullable_type il cui tipo sottostante è un enum_type.An implicit enumeration conversion permits the decimal_integer_literal 0 to be converted to any enum_type and to any nullable_type whose underlying type is an enum_type. Nel secondo caso la conversione viene valutata mediante la conversione nel enum_type sottostante e il wrapping del risultato (tipi nullable).In the latter case the conversion is evaluated by converting to the underlying enum_type and wrapping the result (Nullable types).

Conversioni implicite di stringhe interpolateImplicit interpolated string conversions

Una conversione implicita di stringa interpolata consente di convertire un interpolated_string_expression (stringhe interpolate) in System.IFormattable o System.FormattableString (che implementa System.IFormattable).An implicit interpolated string conversion permits an interpolated_string_expression (Interpolated strings) to be converted to System.IFormattable or System.FormattableString (which implements System.IFormattable).

Quando questa conversione viene applicata, un valore stringa non è composto dalla stringa interpolata.When this conversion is applied a string value is not composed from the interpolated string. Viene invece creata un'istanza di System.FormattableString, come descritto in stringhe interpolate.Instead an instance of System.FormattableString is created, as further described in Interpolated strings.

Conversioni implicite NullableImplicit nullable conversions

Le conversioni implicite predefinite che operano su tipi di valore non nullable possono essere utilizzate anche con forme Nullable di tali tipi.Predefined implicit conversions that operate on non-nullable value types can also be used with nullable forms of those types. Per ognuna delle conversioni numeriche implicite e di identità predefinite che convertono da un tipo di valore non nullable S a un tipo di valore non nullable T, esistono le seguenti conversioni implicite Nullable:For each of the predefined implicit identity and numeric conversions that convert from a non-nullable value type S to a non-nullable value type T, the following implicit nullable conversions exist:

  • Conversione implicita da S? a T?.An implicit conversion from S? to T?.
  • Conversione implicita da S a T?.An implicit conversion from S to T?.

La valutazione di una conversione Nullable implicita basata su una conversione sottostante da S a T procede come segue:Evaluation of an implicit nullable conversion based on an underlying conversion from S to T proceeds as follows:

  • Se la conversione Nullable è da S? a T?:If the nullable conversion is from S? to T?:

    • Se il valore di origine è null (HasValue proprietà è false), il risultato è il valore null di tipo T?.If the source value is null (HasValue property is false), the result is the null value of type T?.
    • In caso contrario, la conversione viene valutata come annullamento del wrapping da S? a S, seguito dalla conversione sottostante da S a T, seguito da un wrapping (tipi nullable) da T a T?.Otherwise, the conversion is evaluated as an unwrapping from S? to S, followed by the underlying conversion from S to T, followed by a wrapping (Nullable types) from T to T?.
  • Se la conversione Nullable è da S a T?, la conversione viene valutata come la conversione sottostante da S a T seguito da un wrapping da T a T?.If the nullable conversion is from S to T?, the conversion is evaluated as the underlying conversion from S to T followed by a wrapping from T to T?.

Conversioni di valori letterali nullNull literal conversions

Esiste una conversione implicita dal valore letterale null a qualsiasi tipo Nullable.An implicit conversion exists from the null literal to any nullable type. Questa conversione produce il valore null (tipi nullable) del tipo nullable specificato.This conversion produces the null value (Nullable types) of the given nullable type.

Conversioni di riferimenti impliciteImplicit reference conversions

Le conversioni implicite dei riferimenti sono:The implicit reference conversions are:

  • Da qualsiasi reference_type object e dynamic.From any reference_type to object and dynamic.
  • Da qualsiasi class_type S a qualsiasi class_type T, fornito S viene derivato da T.From any class_type S to any class_type T, provided S is derived from T.
  • Da qualsiasi class_type S a qualsiasi INTERFACE_TYPE T, fornito S implementa T.From any class_type S to any interface_type T, provided S implements T.
  • Da qualsiasi interface_type S a qualsiasi INTERFACE_TYPE T, fornito S viene derivato da T.From any interface_type S to any interface_type T, provided S is derived from T.
  • Da un array_type S con un tipo di elemento SE a un array_type T con un tipo di elemento TE, purché siano soddisfatte tutte le condizioni seguenti:From an array_type S with an element type SE to an array_type T with an element type TE, provided all of the following are true:
    • S e T differiscono solo per il tipo di elemento.S and T differ only in element type. In altre parole, S e T hanno lo stesso numero di dimensioni.In other words, S and T have the same number of dimensions.
    • SE e TE sono reference_types.Both SE and TE are reference_types.
    • Una conversione implicita di riferimento esiste dal SE al TE.An implicit reference conversion exists from SE to TE.
  • Da qualsiasi array_type System.Array e dalle interfacce che implementa.From any array_type to System.Array and the interfaces it implements.
  • Da un tipo di matrice unidimensionale S[] System.Collections.Generic.IList<T> e le relative interfacce di base, purché sia presente un'identità implicita o una conversione di riferimenti da S a T.From a single-dimensional array type S[] to System.Collections.Generic.IList<T> and its base interfaces, provided that there is an implicit identity or reference conversion from S to T.
  • Da qualsiasi delegate_type System.Delegate e dalle interfacce che implementa.From any delegate_type to System.Delegate and the interfaces it implements.
  • Dal valore letterale null a qualsiasi reference_type.From the null literal to any reference_type.
  • Da qualsiasi reference_type a un reference_type T se è presente un'identità implicita o una conversione di riferimenti a un T0 reference_type e T0 dispone di una conversione di identità in T.From any reference_type to a reference_type T if it has an implicit identity or reference conversion to a reference_type T0 and T0 has an identity conversion to T.
  • Da qualsiasi reference_type a un tipo di interfaccia o delegato T se è presente un'identità implicita o una conversione di un riferimento a un tipo di interfaccia o delegato T0 e T0 è una conversione della varianza (conversione della varianza) a T.From any reference_type to an interface or delegate type T if it has an implicit identity or reference conversion to an interface or delegate type T0 and T0 is variance-convertible (Variance conversion) to T.
  • Conversioni implicite che coinvolgono parametri di tipo noti come tipi di riferimento.Implicit conversions involving type parameters that are known to be reference types. Per ulteriori informazioni sulle conversioni implicite che coinvolgono parametri di tipo, vedere conversioni implicite che coinvolgono parametri di tipo .See Implicit conversions involving type parameters for more details on implicit conversions involving type parameters.

Le conversioni implicite dei riferimenti sono quelle conversioni tra reference_types che è possibile dimostrare di avere sempre esito positivo e pertanto non richiedono alcun controllo in fase di esecuzione.The implicit reference conversions are those conversions between reference_types that can be proven to always succeed, and therefore require no checks at run-time.

Le conversioni dei riferimenti, implicite o esplicite, non modificano mai l'identità referenziale dell'oggetto da convertire.Reference conversions, implicit or explicit, never change the referential identity of the object being converted. In altre parole, mentre una conversione di riferimento può modificare il tipo di riferimento, non modifica mai il tipo o il valore dell'oggetto a cui si fa riferimento.In other words, while a reference conversion may change the type of the reference, it never changes the type or value of the object being referred to.

Conversioni boxingBoxing conversions

Una conversione boxing consente a un value_type di essere convertito in modo implicito in un tipo di riferimento.A boxing conversion permits a value_type to be implicitly converted to a reference type. Esiste una conversione boxing da qualsiasi non_nullable_value_type per object e dynamic, per System.ValueType e per qualsiasi interface_type implementato dal non_nullable_value_type.A boxing conversion exists from any non_nullable_value_type to object and dynamic, to System.ValueType and to any interface_type implemented by the non_nullable_value_type. Inoltre, un enum_type può essere convertito nel tipo System.Enum.Furthermore an enum_type can be converted to the type System.Enum.

Una conversione boxing esiste da un nullable_type a un tipo riferimento, se e solo se esiste una conversione boxing dall' non_nullable_value_type sottostante al tipo di riferimento.A boxing conversion exists from a nullable_type to a reference type, if and only if a boxing conversion exists from the underlying non_nullable_value_type to the reference type.

Un tipo di valore ha una conversione boxing in un tipo di interfaccia I se è presente una conversione boxing in un tipo di interfaccia I0 e I0 ha una conversione di identità in I.A value type has a boxing conversion to an interface type I if it has a boxing conversion to an interface type I0 and I0 has an identity conversion to I.

Un tipo di valore ha una conversione boxing in un tipo di interfaccia I se è presente una conversione boxing in un tipo di interfaccia o delegato I0 e I0 è una conversione della varianza (conversione della varianza) a I.A value type has a boxing conversion to an interface type I if it has a boxing conversion to an interface or delegate type I0 and I0 is variance-convertible (Variance conversion) to I.

La conversione boxing di un valore non_nullable_value_type consiste nell'allocazione di un'istanza dell'oggetto e nella copia del valore value_type in tale istanza.Boxing a value of a non_nullable_value_type consists of allocating an object instance and copying the value_type value into that instance. È possibile eseguire il Boxing di uno struct al tipo System.ValueType, perché si tratta di una classe di base per tutti gli struct (ereditarietà).A struct can be boxed to the type System.ValueType, since that is a base class for all structs (Inheritance).

Il Boxing di un valore di un nullable_type procede come segue:Boxing a value of a nullable_type proceeds as follows:

  • Se il valore di origine è null (HasValue proprietà è false), il risultato è un riferimento null del tipo di destinazione.If the source value is null (HasValue property is false), the result is a null reference of the target type.
  • In caso contrario, il risultato è un riferimento a un T boxed prodotto dalla rimozione del wrapping e dalla conversione boxing del valore di origine.Otherwise, the result is a reference to a boxed T produced by unwrapping and boxing the source value.

Le conversioni boxing sono descritte ulteriormente nelle conversioni boxing.Boxing conversions are described further in Boxing conversions.

Conversioni dinamiche impliciteImplicit dynamic conversions

Una conversione dinamica implicita esiste da un'espressione di tipo dynamic a qualsiasi tipo T.An implicit dynamic conversion exists from an expression of type dynamic to any type T. La conversione è associata dinamicamente (associazione dinamica), il che significa che una conversione implicita verrà cercata in fase di esecuzione dal tipo in fase di esecuzione dell'espressione T.The conversion is dynamically bound (Dynamic binding), which means that an implicit conversion will be sought at run-time from the run-time type of the expression to T. Se non viene trovata alcuna conversione, viene generata un'eccezione in fase di esecuzione.If no conversion is found, a run-time exception is thrown.

Si noti che questa conversione implicita viola apparentemente il Consiglio all'inizio di conversioni implicite che una conversione implicita non deve mai generare un'eccezione.Note that this implicit conversion seemingly violates the advice in the beginning of Implicit conversions that an implicit conversion should never cause an exception. Tuttavia, non è la conversione stessa, ma la ricerca della conversione che genera l'eccezione.However it is not the conversion itself, but the finding of the conversion that causes the exception. Il rischio di eccezioni in fase di esecuzione è intrinseco all'utilizzo dell'associazione dinamica.The risk of run-time exceptions is inherent in the use of dynamic binding. Se non si desidera un binding dinamico della conversione, l'espressione può essere prima convertita in objecte quindi nel tipo desiderato.If dynamic binding of the conversion is not desired, the expression can be first converted to object, and then to the desired type.

Nell'esempio seguente vengono illustrate le conversioni dinamiche implicite:The following example illustrates implicit dynamic conversions:

object o  = "object"
dynamic d = "dynamic";

string s1 = o; // Fails at compile-time -- no conversion exists
string s2 = d; // Compiles and succeeds at run-time
int i     = d; // Compiles but fails at run-time -- no conversion exists

Le assegnazioni per s2 e i entrambi utilizzano conversioni dinamiche implicite, in cui l'associazione delle operazioni viene sospesa fino alla fase di esecuzione.The assignments to s2 and i both employ implicit dynamic conversions, where the binding of the operations is suspended until run-time. In fase di esecuzione, le conversioni implicite vengono cercate dal tipo in fase di esecuzione d -- string, al tipo di destinazione.At run-time, implicit conversions are sought from the run-time type of d -- string -- to the target type. È stata rilevata una conversione da string ma non da int.A conversion is found to string but not to int.

Conversioni implicite di espressioni costantiImplicit constant expression conversions

Una conversione implicita di espressioni costanti consente le conversioni seguenti:An implicit constant expression conversion permits the following conversions:

  • Un constant_expression (espressioni costanti) di tipo int può essere convertito nel tipo sbyte, byte, short, ushort, uinto ulong, a condizione che il valore del constant_expression sia compreso nell'intervallo del tipo di destinazione.A constant_expression (Constant expressions) of type int can be converted to type sbyte, byte, short, ushort, uint, or ulong, provided the value of the constant_expression is within the range of the destination type.
  • Un constant_expression di tipo long può essere convertito nel tipo ulong, purché il valore del constant_expression non sia negativo.A constant_expression of type long can be converted to type ulong, provided the value of the constant_expression is not negative.

Conversioni implicite che coinvolgono parametri di tipoImplicit conversions involving type parameters

Per un parametro di tipo specificato esistono le conversioni implicite seguenti T:The following implicit conversions exist for a given type parameter T:

  • Da T alla classe base effettiva C, da T a qualsiasi classe di base di Ce da T a qualsiasi interfaccia implementata da C.From T to its effective base class C, from T to any base class of C, and from T to any interface implemented by C. In fase di esecuzione, se T è un tipo di valore, la conversione viene eseguita come conversione boxing.At run-time, if T is a value type, the conversion is executed as a boxing conversion. In caso contrario, la conversione viene eseguita come conversione di un riferimento implicito o conversione di identità.Otherwise, the conversion is executed as an implicit reference conversion or identity conversion.
  • Da T a un tipo di interfaccia I nel set di interfacce effettivo Te da T a qualsiasi interfaccia di base di I.From T to an interface type I in T's effective interface set and from T to any base interface of I. In fase di esecuzione, se T è un tipo di valore, la conversione viene eseguita come conversione boxing.At run-time, if T is a value type, the conversion is executed as a boxing conversion. In caso contrario, la conversione viene eseguita come conversione di un riferimento implicito o conversione di identità.Otherwise, the conversion is executed as an implicit reference conversion or identity conversion.
  • Da T a un parametro di tipo U, fornito T dipende da U (vincoli di parametro di tipo).From T to a type parameter U, provided T depends on U (Type parameter constraints). In fase di esecuzione, se U è un tipo di valore, T e U sono necessariamente dello stesso tipo e non viene eseguita alcuna conversione.At run-time, if U is a value type, then T and U are necessarily the same type and no conversion is performed. In caso contrario, se T è un tipo valore, la conversione viene eseguita come conversione boxing.Otherwise, if T is a value type, the conversion is executed as a boxing conversion. In caso contrario, la conversione viene eseguita come conversione di un riferimento implicito o conversione di identità.Otherwise, the conversion is executed as an implicit reference conversion or identity conversion.
  • Dal valore letterale null a T, fornito T è noto come tipo di riferimento.From the null literal to T, provided T is known to be a reference type.
  • Da T a un tipo di riferimento I se dispone di una conversione implicita in un tipo riferimento S0 e S0 ha una conversione di identità in S.From T to a reference type I if it has an implicit conversion to a reference type S0 and S0 has an identity conversion to S. In fase di esecuzione la conversione viene eseguita in modo analogo alla conversione in S0.At run-time the conversion is executed the same way as the conversion to S0.
  • Da T a un tipo di interfaccia I se dispone di una conversione implicita in un tipo di interfaccia o delegato I0 e I0 è una varianza convertibile in I (conversione della varianza).From T to an interface type I if it has an implicit conversion to an interface or delegate type I0 and I0 is variance-convertible to I (Variance conversion). In fase di esecuzione, se T è un tipo di valore, la conversione viene eseguita come conversione boxing.At run-time, if T is a value type, the conversion is executed as a boxing conversion. In caso contrario, la conversione viene eseguita come conversione di un riferimento implicito o conversione di identità.Otherwise, the conversion is executed as an implicit reference conversion or identity conversion.

Se T è noto come tipo di riferimento (vincoli di parametro di tipo), le conversioni precedenti vengono tutte classificate come conversioni implicite dei riferimenti (conversioni diriferimenti implicite).If T is known to be a reference type (Type parameter constraints), the conversions above are all classified as implicit reference conversions (Implicit reference conversions). Se T non è noto come tipo di riferimento, le conversioni precedenti vengono classificate come conversioni boxing (conversioniBoxing).If T is not known to be a reference type, the conversions above are classified as boxing conversions (Boxing conversions).

Conversioni implicite definite dall'utenteUser-defined implicit conversions

Una conversione implicita definita dall'utente è costituita da una conversione implicita standard facoltativa, seguita dall'esecuzione di un operatore di conversione implicita definito dall'utente, seguita da un'altra conversione implicita standard facoltativa.A user-defined implicit conversion consists of an optional standard implicit conversion, followed by execution of a user-defined implicit conversion operator, followed by another optional standard implicit conversion. Le regole esatte per la valutazione delle conversioni implicite definite dall'utente sono descritte in elaborazione di conversioni implicite definite dall'utente.The exact rules for evaluating user-defined implicit conversions are described in Processing of user-defined implicit conversions.

Conversioni di funzioni anonime e conversioni di gruppi di metodiAnonymous function conversions and method group conversions

Le funzioni anonime e i gruppi di metodi non hanno tipi in e di se stessi, ma possono essere convertiti in modo implicito in tipi delegati o tipi di alberi delle espressioni.Anonymous functions and method groups do not have types in and of themselves, but may be implicitly converted to delegate types or expression tree types. Le conversioni di funzioni anonime sono descritte in modo più dettagliato nelle conversioni di funzioni anonime e nelle conversioni di gruppi di metodi nelle conversioni dei gruppi di metodi.Anonymous function conversions are described in more detail in Anonymous function conversions and method group conversions in Method group conversions.

Conversioni espliciteExplicit conversions

Le conversioni seguenti sono classificate come conversioni esplicite:The following conversions are classified as explicit conversions:

  • Tutte le conversioni implicite.All implicit conversions.
  • Conversioni numeriche esplicite.Explicit numeric conversions.
  • Conversioni esplicite dell'enumerazione.Explicit enumeration conversions.
  • Conversioni esplicite Nullable.Explicit nullable conversions.
  • Conversioni esplicite dei riferimenti.Explicit reference conversions.
  • Conversioni esplicite dell'interfaccia.Explicit interface conversions.
  • Conversione unboxing.Unboxing conversions.
  • Conversioni dinamiche espliciteExplicit dynamic conversions
  • Conversioni esplicite definite dall'utente.User-defined explicit conversions.

Le conversioni esplicite possono verificarsi nelle espressioni cast (espressioni cast).Explicit conversions can occur in cast expressions (Cast expressions).

Il set di conversioni esplicite include tutte le conversioni implicite.The set of explicit conversions includes all implicit conversions. Ciò significa che sono consentite espressioni cast ridondanti.This means that redundant cast expressions are allowed.

Le conversioni esplicite che non sono conversioni implicite sono conversioni che non possono essere verificate per sempre esito positivo, le conversioni che potrebbero perdere informazioni e le conversioni tra domini di tipi sufficientemente diversi da Merit esplicito notazione.The explicit conversions that are not implicit conversions are conversions that cannot be proven to always succeed, conversions that are known to possibly lose information, and conversions across domains of types sufficiently different to merit explicit notation.

Conversioni numeriche espliciteExplicit numeric conversions

Le conversioni numeriche esplicite sono le conversioni da un numeric_type a un altro numeric_type per cui non esiste già una conversione numerica implicita (conversioni numeriche implicite):The explicit numeric conversions are the conversions from a numeric_type to another numeric_type for which an implicit numeric conversion (Implicit numeric conversions) does not already exist:

  • Da sbyte a byte, ushort, uint, ulongo char.From sbyte to byte, ushort, uint, ulong, or char.
  • Da byte a sbyte e char.From byte to sbyte and char.
  • Da short a sbyte, byte, ushort, uint, ulongo char.From short to sbyte, byte, ushort, uint, ulong, or char.
  • Da ushort a sbyte, byte, shorto char.From ushort to sbyte, byte, short, or char.
  • Da int a sbyte, byte, short, ushort, uint, ulongo char.From int to sbyte, byte, short, ushort, uint, ulong, or char.
  • Da uint a sbyte, byte, short, ushort, into char.From uint to sbyte, byte, short, ushort, int, or char.
  • Da long a sbyte, byte, short, ushort, int, uint, ulongo char.From long to sbyte, byte, short, ushort, int, uint, ulong, or char.
  • Da ulong a sbyte, byte, short, ushort, int, uint, longo char.From ulong to sbyte, byte, short, ushort, int, uint, long, or char.
  • Da char a sbyte, byteo short.From char to sbyte, byte, or short.
  • Da float a sbyte, byte, short, ushort, int, uint, long, ulong, charo decimal.From float to sbyte, byte, short, ushort, int, uint, long, ulong, char, or decimal.
  • Da double a sbyte, byte, short, ushort, int, uint, long, ulong, char, floato decimal.From double to sbyte, byte, short, ushort, int, uint, long, ulong, char, float, or decimal.
  • Da decimal a sbyte, byte, short, ushort, int, uint, long, ulong, char, floato double.From decimal to sbyte, byte, short, ushort, int, uint, long, ulong, char, float, or double.

Poiché le conversioni esplicite includono tutte le conversioni numeriche implicite ed esplicite, è sempre possibile eseguire la conversione da qualsiasi numeric_type a qualsiasi altra numeric_type utilizzando un'espressione cast (espressioni cast).Because the explicit conversions include all implicit and explicit numeric conversions, it is always possible to convert from any numeric_type to any other numeric_type using a cast expression (Cast expressions).

Le conversioni numeriche esplicite potrebbero perdere informazioni o causare la generazione di eccezioni.The explicit numeric conversions possibly lose information or possibly cause exceptions to be thrown. Una conversione numerica esplicita viene elaborata come segue:An explicit numeric conversion is processed as follows:

  • Per una conversione da un tipo integrale a un altro tipo integrale, l'elaborazione dipende dal contesto di controllo dell'overflow (gli operatori checked e unchecked) in cui viene eseguita la conversione:For a conversion from an integral type to another integral type, the processing depends on the overflow checking context (The checked and unchecked operators) in which the conversion takes place:
    • In un contesto di checked la conversione ha esito positivo se il valore dell'operando di origine è compreso nell'intervallo del tipo di destinazione, ma genera un'System.OverflowException se il valore dell'operando di origine non è compreso nell'intervallo del tipo di destinazione.In a checked context, the conversion succeeds if the value of the source operand is within the range of the destination type, but throws a System.OverflowException if the value of the source operand is outside the range of the destination type.
    • In un contesto unchecked la conversione ha sempre esito positivo e procede come segue.In an unchecked context, the conversion always succeeds, and proceeds as follows.
      • Se il tipo di origine è maggiore del tipo di destinazione, il valore di origine viene troncato rimuovendo i relativi "extra" bit più rilevanti.If the source type is larger than the destination type, then the source value is truncated by discarding its "extra" most significant bits. Il risultato viene quindi trattato come un valore del tipo di destinazione.The result is then treated as a value of the destination type.
      • Se il tipo di origine è inferiore al tipo di destinazione, il valore di origine ha estensione firma o estensione zero in modo da avere le stesse dimensioni del tipo di destinazione.If the source type is smaller than the destination type, then the source value is either sign-extended or zero-extended so that it is the same size as the destination type. L'estensione firma viene usata se il tipo di origine dispone della firma; l'estensione zero viene usata se il tipo di origine è privo di firma.Sign-extension is used if the source type is signed; zero-extension is used if the source type is unsigned. Il risultato viene quindi trattato come un valore del tipo di destinazione.The result is then treated as a value of the destination type.
      • Se il tipo di origine ha le stesse dimensioni del tipo di destinazione, il valore di origine viene considerato un valore del tipo di destinazione.If the source type is the same size as the destination type, then the source value is treated as a value of the destination type.
  • Per una conversione da decimal a un tipo integrale, il valore di origine viene arrotondato per eccesso al valore integrale più vicino e questo valore integrale diventa il risultato della conversione.For a conversion from decimal to an integral type, the source value is rounded towards zero to the nearest integral value, and this integral value becomes the result of the conversion. Se il valore integrale risultante non rientra nell'intervallo del tipo di destinazione, viene generata un'System.OverflowException.If the resulting integral value is outside the range of the destination type, a System.OverflowException is thrown.
  • Per una conversione da float o double a un tipo integrale, l'elaborazione dipende dal contesto di controllo dell'overflow (gli operatori checked e unchecked) in cui viene eseguita la conversione:For a conversion from float or double to an integral type, the processing depends on the overflow checking context (The checked and unchecked operators) in which the conversion takes place:
    • In un contesto di checked la conversione procede come segue:In a checked context, the conversion proceeds as follows:
      • Se il valore dell'operando è NaN o infinite, viene generata un'System.OverflowException.If the value of the operand is NaN or infinite, a System.OverflowException is thrown.
      • In caso contrario, l'operando di origine viene arrotondato verso lo zero al valore integrale più vicino.Otherwise, the source operand is rounded towards zero to the nearest integral value. Se questo valore integrale è compreso nell'intervallo del tipo di destinazione, questo valore è il risultato della conversione.If this integral value is within the range of the destination type then this value is the result of the conversion.
      • In caso contrario viene generata un'eccezione System.OverflowException.Otherwise, a System.OverflowException is thrown.
    • In un contesto unchecked la conversione ha sempre esito positivo e procede come segue.In an unchecked context, the conversion always succeeds, and proceeds as follows.
      • Se il valore dell'operando è NaN o infinito, il risultato della conversione è un valore non specificato del tipo di destinazione.If the value of the operand is NaN or infinite, the result of the conversion is an unspecified value of the destination type.
      • In caso contrario, l'operando di origine viene arrotondato verso lo zero al valore integrale più vicino.Otherwise, the source operand is rounded towards zero to the nearest integral value. Se questo valore integrale è compreso nell'intervallo del tipo di destinazione, questo valore è il risultato della conversione.If this integral value is within the range of the destination type then this value is the result of the conversion.
      • In caso contrario, il risultato della conversione è un valore non specificato del tipo di destinazione.Otherwise, the result of the conversion is an unspecified value of the destination type.
  • Per una conversione da double a float, il valore del double viene arrotondato al valore float più vicino.For a conversion from double to float, the double value is rounded to the nearest float value. Se il valore double è troppo piccolo per essere rappresentato come float, il risultato diventa zero positivo o negativo.If the double value is too small to represent as a float, the result becomes positive zero or negative zero. Se il valore double è troppo grande per essere rappresentato come float, il risultato diventa un infinito positivo o un infinito negativo.If the double value is too large to represent as a float, the result becomes positive infinity or negative infinity. Se il valore double è NaN, anche il risultato è NaN.If the double value is NaN, the result is also NaN.
  • Per una conversione da float o da double a decimal, il valore di origine viene convertito in decimal rappresentazione e arrotondato al numero più vicino dopo la posizione decimale 28, se necessario (tipo decimale).For a conversion from float or double to decimal, the source value is converted to decimal representation and rounded to the nearest number after the 28th decimal place if required (The decimal type). Se il valore di origine è troppo piccolo per essere rappresentato come decimal, il risultato diventa zero.If the source value is too small to represent as a decimal, the result becomes zero. Se il valore di origine è NaN, infinito o troppo grande per essere rappresentato come decimal, viene generata un'System.OverflowException.If the source value is NaN, infinity, or too large to represent as a decimal, a System.OverflowException is thrown.
  • Per una conversione da decimal a float o double, il valore decimal viene arrotondato al valore double o float più vicino.For a conversion from decimal to float or double, the decimal value is rounded to the nearest double or float value. Sebbene questa conversione possa perdere precisione, non genera mai un'eccezione.While this conversion may lose precision, it never causes an exception to be thrown.

Conversioni esplicite dell'enumerazioneExplicit enumeration conversions

Le conversioni esplicite dell'enumerazione sono:The explicit enumeration conversions are:

  • Da sbyte, byte, short, ushort, int, uint, long, ulong, char, float, doubleo decimal a qualsiasi enum_type.From sbyte, byte, short, ushort, int, uint, long, ulong, char, float, double, or decimal to any enum_type.
  • Da qualsiasi enum_type a sbyte, byte, short, ushort, int, uint, long, ulong, char, float, doubleo decimal.From any enum_type to sbyte, byte, short, ushort, int, uint, long, ulong, char, float, double, or decimal.
  • Da qualsiasi enum_type a qualsiasi altra enum_type.From any enum_type to any other enum_type.

Una conversione esplicita dell'enumerazione tra due tipi viene elaborata trattando qualsiasi enum_type partecipante come tipo sottostante di tale enum_typee quindi eseguendo una conversione numerica implicita o esplicita tra i tipi risultanti.An explicit enumeration conversion between two types is processed by treating any participating enum_type as the underlying type of that enum_type, and then performing an implicit or explicit numeric conversion between the resulting types. Ad esempio, dato un enum_type E con e il tipo sottostante di int, una conversione da E a byte viene elaborata come conversione numerica esplicita (conversioni numeriche esplicite) da int a bytee una conversione da byte a E viene elaborata come conversione numerica implicita (conversioni numeriche implicite) da byte a int.For example, given an enum_type E with and underlying type of int, a conversion from E to byte is processed as an explicit numeric conversion (Explicit numeric conversions) from int to byte, and a conversion from byte to E is processed as an implicit numeric conversion (Implicit numeric conversions) from byte to int.

Conversioni esplicite NullableExplicit nullable conversions

Le conversioni esplicite Nullable consentono conversioni esplicite predefinite che operano su tipi di valore non nullable per essere utilizzate anche con forme Nullable di tali tipi.Explicit nullable conversions permit predefined explicit conversions that operate on non-nullable value types to also be used with nullable forms of those types. Per ognuna delle conversioni esplicite predefinite che consentono di eseguire la conversione da un tipo di valore non nullable S a un tipo di valore non nullable T (conversione di identità, conversioni numeriche implicite, conversioni di enumerazione implicite, conversioni numeriche esplicitee conversioni esplicite dell'enumerazione), esistono le seguenti conversioni Nullable:For each of the predefined explicit conversions that convert from a non-nullable value type S to a non-nullable value type T (Identity conversion, Implicit numeric conversions, Implicit enumeration conversions, Explicit numeric conversions, and Explicit enumeration conversions), the following nullable conversions exist:

  • Conversione esplicita da S? a T?.An explicit conversion from S? to T?.
  • Conversione esplicita da S a T?.An explicit conversion from S to T?.
  • Conversione esplicita da S? a T.An explicit conversion from S? to T.

La valutazione di una conversione Nullable basata su una conversione sottostante da S a T procede come segue:Evaluation of a nullable conversion based on an underlying conversion from S to T proceeds as follows:

  • Se la conversione Nullable è da S? a T?:If the nullable conversion is from S? to T?:
    • Se il valore di origine è null (HasValue proprietà è false), il risultato è il valore null di tipo T?.If the source value is null (HasValue property is false), the result is the null value of type T?.
    • In caso contrario, la conversione viene valutata come annullamento del wrapping da S? a S, seguito dalla conversione sottostante da S a T, seguito da un wrapping da T a T?.Otherwise, the conversion is evaluated as an unwrapping from S? to S, followed by the underlying conversion from S to T, followed by a wrapping from T to T?.
  • Se la conversione Nullable è da S a T?, la conversione viene valutata come la conversione sottostante da S a T seguito da un wrapping da T a T?.If the nullable conversion is from S to T?, the conversion is evaluated as the underlying conversion from S to T followed by a wrapping from T to T?.
  • Se la conversione Nullable è da S? a T, la conversione viene valutata come annullamento del wrapping da S? a S seguito dalla conversione sottostante da S a T.If the nullable conversion is from S? to T, the conversion is evaluated as an unwrapping from S? to S followed by the underlying conversion from S to T.

Si noti che un tentativo di annullare il wrapping di un valore Nullable genererà un'eccezione se il valore è null.Note that an attempt to unwrap a nullable value will throw an exception if the value is null.

Conversioni esplicite dei riferimentiExplicit reference conversions

Le conversioni esplicite dei riferimenti sono:The explicit reference conversions are:

  • Da object e dynamic ad altri reference_type.From object and dynamic to any other reference_type.
  • Da qualsiasi class_type S a qualsiasi class_type T, fornito S è una classe di base di T.From any class_type S to any class_type T, provided S is a base class of T.
  • Da qualsiasi class_type S a qualsiasi INTERFACE_TYPE T, fornito S non è sealed e fornito S non implementa T.From any class_type S to any interface_type T, provided S is not sealed and provided S does not implement T.
  • Da qualsiasi interface_type S a qualsiasi class_type T, fornito T non è sealed o fornito T implementa S.From any interface_type S to any class_type T, provided T is not sealed or provided T implements S.
  • Da qualsiasi interface_type S a qualsiasi INTERFACE_TYPE T, fornito S non è derivato da T.From any interface_type S to any interface_type T, provided S is not derived from T.
  • Da un array_type S con un tipo di elemento SE a un array_type T con un tipo di elemento TE, purché siano soddisfatte tutte le condizioni seguenti:From an array_type S with an element type SE to an array_type T with an element type TE, provided all of the following are true:
    • S e T differiscono solo per il tipo di elemento.S and T differ only in element type. In altre parole, S e T hanno lo stesso numero di dimensioni.In other words, S and T have the same number of dimensions.
    • SE e TE sono reference_types.Both SE and TE are reference_types.
    • Una conversione esplicita del riferimento esiste dal SE al TE.An explicit reference conversion exists from SE to TE.
  • Da System.Array e dalle interfacce implementate in qualsiasi array_type.From System.Array and the interfaces it implements to any array_type.
  • Da un tipo di matrice unidimensionale S[] System.Collections.Generic.IList<T> e le interfacce di base, purché sia presente una conversione esplicita del riferimento da S a T.From a single-dimensional array type S[] to System.Collections.Generic.IList<T> and its base interfaces, provided that there is an explicit reference conversion from S to T.
  • Da System.Collections.Generic.IList<S> e dalle relative interfacce di base a un tipo di matrice unidimensionale T[], a condizione che esista un'identità esplicita o una conversione di riferimenti da S a T.From System.Collections.Generic.IList<S> and its base interfaces to a single-dimensional array type T[], provided that there is an explicit identity or reference conversion from S to T.
  • Da System.Delegate e dalle interfacce implementate in qualsiasi delegate_type.From System.Delegate and the interfaces it implements to any delegate_type.
  • Da un tipo riferimento a un tipo riferimento T se dispone di una conversione esplicita di un riferimento a un tipo di riferimento T0 e T0 ha una conversione di identità T.From a reference type to a reference type T if it has an explicit reference conversion to a reference type T0 and T0 has an identity conversion T.
  • Da un tipo di riferimento a un tipo di interfaccia o delegato T se è presente una conversione esplicita del riferimento a un'interfaccia o a un tipo di delegato T0 e T0 è la conversione della varianza in T o T è la conversione della varianza a T0 (conversione della varianza).From a reference type to an interface or delegate type T if it has an explicit reference conversion to an interface or delegate type T0 and either T0 is variance-convertible to T or T is variance-convertible to T0 (Variance conversion).
  • Da D<S1...Sn> a D<T1...Tn> dove D<X1...Xn> è un tipo delegato generico, D<S1...Sn> non è compatibile con o è identico a D<T1...Tn>e per ogni parametro di tipo Xi di D il seguente:From D<S1...Sn> to D<T1...Tn> where D<X1...Xn> is a generic delegate type, D<S1...Sn> is not compatible with or identical to D<T1...Tn>, and for each type parameter Xi of D the following holds:
    • Se Xi è invariante, Si è identico a Ti.If Xi is invariant, then Si is identical to Ti.
    • Se Xi è covariante, esiste un'identità implicita o esplicita o una conversione di riferimenti da Si a Ti.If Xi is covariant, then there is an implicit or explicit identity or reference conversion from Si to Ti.
    • Se Xi è controvariante, Si e Ti sono entrambi tipi di riferimento o identici.If Xi is contravariant, then Si and Ti are either identical or both reference types.
  • Conversioni esplicite che coinvolgono parametri di tipo noti come tipi di riferimento.Explicit conversions involving type parameters that are known to be reference types. Per ulteriori informazioni sulle conversioni esplicite che coinvolgono parametri di tipo, vedere conversioni esplicite che coinvolgono parametri di tipo.For more details on explicit conversions involving type parameters, see Explicit conversions involving type parameters.

Le conversioni esplicite dei riferimenti sono quelle conversioni tra i tipi di riferimento che richiedono controlli run-time per assicurarsi che siano corrette.The explicit reference conversions are those conversions between reference-types that require run-time checks to ensure they are correct.

Affinché una conversione esplicita di un riferimento abbia esito positivo in fase di esecuzione, il valore dell'operando di origine deve essere nulloppure il tipo effettivo dell'oggetto a cui fa riferimento l'operando di origine deve essere un tipo che può essere convertito nel tipo di destinazione mediante una conversione implicita di riferimento (conversioni di riferimenti implicite) o conversione boxing (conversioni boxing).For an explicit reference conversion to succeed at run-time, the value of the source operand must be null, or the actual type of the object referenced by the source operand must be a type that can be converted to the destination type by an implicit reference conversion (Implicit reference conversions) or boxing conversion (Boxing conversions). Se una conversione esplicita del riferimento non riesce, viene generata un'System.InvalidCastException.If an explicit reference conversion fails, a System.InvalidCastException is thrown.

Le conversioni dei riferimenti, implicite o esplicite, non modificano mai l'identità referenziale dell'oggetto da convertire.Reference conversions, implicit or explicit, never change the referential identity of the object being converted. In altre parole, mentre una conversione di riferimento può modificare il tipo di riferimento, non modifica mai il tipo o il valore dell'oggetto a cui si fa riferimento.In other words, while a reference conversion may change the type of the reference, it never changes the type or value of the object being referred to.

Conversione unboxingUnboxing conversions

Una conversione unboxing consente la conversione esplicita di un tipo di riferimento in un value_type.An unboxing conversion permits a reference type to be explicitly converted to a value_type. Esiste una conversione unboxing dai tipi object, dynamic e System.ValueType a qualsiasi non_nullable_value_typee da qualsiasi interface_type a qualsiasi non_nullable_value_type che implementi la INTERFACE_TYPE.An unboxing conversion exists from the types object, dynamic and System.ValueType to any non_nullable_value_type, and from any interface_type to any non_nullable_value_type that implements the interface_type. Inoltre, il tipo System.Enum può essere unboxed per qualsiasi enum_type.Furthermore type System.Enum can be unboxed to any enum_type.

Una conversione unboxing esiste da un tipo di riferimento a un nullable_type se esiste una conversione unboxing dal tipo di riferimento al non_nullable_value_type sottostante della nullable_type.An unboxing conversion exists from a reference type to a nullable_type if an unboxing conversion exists from the reference type to the underlying non_nullable_value_type of the nullable_type.

Un tipo di valore S dispone di una conversione unboxing da un tipo di interfaccia I se è presente una conversione unboxing da un tipo di interfaccia I0 e I0 ha una conversione di identità in I.A value type S has an unboxing conversion from an interface type I if it has an unboxing conversion from an interface type I0 and I0 has an identity conversion to I.

Un tipo di valore S dispone di una conversione unboxing da un tipo di interfaccia I se è presente una conversione unboxing da un tipo di interfaccia o delegato I0 e la I0 è varianza-convertibile in I o I è la varianza-convertibile in I0 (conversione della varianza).A value type S has an unboxing conversion from an interface type I if it has an unboxing conversion from an interface or delegate type I0 and either I0 is variance-convertible to I or I is variance-convertible to I0 (Variance conversion).

Un'operazione di conversione unboxing consiste nel verificare innanzitutto che l'istanza dell'oggetto sia un valore boxed del value_typespecificato e quindi copiare il valore all'esterno dell'istanza.An unboxing operation consists of first checking that the object instance is a boxed value of the given value_type, and then copying the value out of the instance. Se si unboxing un riferimento null a un nullable_type , viene prodotto il valore null del nullable_type.Unboxing a null reference to a nullable_type produces the null value of the nullable_type. Uno struct può essere unboxed dal tipo System.ValueType, perché si tratta di una classe di base per tutti gli struct (ereditarietà).A struct can be unboxed from the type System.ValueType, since that is a base class for all structs (Inheritance).

Le conversioni unboxing sono descritte ulteriormente nelle conversioni unboxing.Unboxing conversions are described further in Unboxing conversions.

Conversioni dinamiche espliciteExplicit dynamic conversions

Una conversione dinamica esplicita esiste da un'espressione di tipo dynamic a qualsiasi tipo T.An explicit dynamic conversion exists from an expression of type dynamic to any type T. La conversione è associata in modo dinamico (associazione dinamica), il che significa che una conversione esplicita verrà cercata in fase di esecuzione dal tipo in fase di esecuzione dell'espressione T.The conversion is dynamically bound (Dynamic binding), which means that an explicit conversion will be sought at run-time from the run-time type of the expression to T. Se non viene trovata alcuna conversione, viene generata un'eccezione in fase di esecuzione.If no conversion is found, a run-time exception is thrown.

Se non si desidera un binding dinamico della conversione, l'espressione può essere prima convertita in objecte quindi nel tipo desiderato.If dynamic binding of the conversion is not desired, the expression can be first converted to object, and then to the desired type.

Si supponga che venga definita la classe seguente:Assume the following class is defined:

class C
{
    int i;

    public C(int i) { this.i = i; }

    public static explicit operator C(string s) 
    {
        return new C(int.Parse(s));
    }
}

Nell'esempio seguente vengono illustrate le conversioni dinamiche esplicite:The following example illustrates explicit dynamic conversions:

object o  = "1";
dynamic d = "2";

var c1 = (C)o; // Compiles, but explicit reference conversion fails
var c2 = (C)d; // Compiles and user defined conversion succeeds

La migliore conversione di o in C viene trovata in fase di compilazione come conversione esplicita dei riferimenti.The best conversion of o to C is found at compile-time to be an explicit reference conversion. Questa operazione ha esito negativo in fase di esecuzione, perché "1" non è in realtà una C.This fails at run-time, because "1" is not in fact a C. La conversione di d in C tuttavia, come conversione dinamica esplicita, viene sospesa in fase di esecuzione, in cui viene rilevata una conversione definita dall'utente dal tipo in fase di esecuzione di d -- string--a C, che ha esito positivo.The conversion of d to C however, as an explicit dynamic conversion, is suspended to run-time, where a user defined conversion from the run-time type of d -- string -- to C is found, and succeeds.

Conversioni esplicite che coinvolgono parametri di tipoExplicit conversions involving type parameters

Per un parametro di tipo specificato esistono le conversioni esplicite seguenti T:The following explicit conversions exist for a given type parameter T:

  • Dalla classe base valida C di T per T e da qualsiasi classe di base di C a T.From the effective base class C of T to T and from any base class of C to T. In fase di esecuzione, se T è un tipo di valore, la conversione viene eseguita come conversione unboxing.At run-time, if T is a value type, the conversion is executed as an unboxing conversion. In caso contrario, la conversione viene eseguita come conversione esplicita di un riferimento o conversione di identità.Otherwise, the conversion is executed as an explicit reference conversion or identity conversion.
  • Da qualsiasi tipo di interfaccia a T.From any interface type to T. In fase di esecuzione, se T è un tipo di valore, la conversione viene eseguita come conversione unboxing.At run-time, if T is a value type, the conversion is executed as an unboxing conversion. In caso contrario, la conversione viene eseguita come conversione esplicita di un riferimento o conversione di identità.Otherwise, the conversion is executed as an explicit reference conversion or identity conversion.
  • Da T a qualsiasi interface_type I purché non esista già una conversione implicita da T a I.From T to any interface_type I provided there is not already an implicit conversion from T to I. In fase di esecuzione, se T è un tipo valore, la conversione viene eseguita come conversione boxing seguita da una conversione esplicita del riferimento.At run-time, if T is a value type, the conversion is executed as a boxing conversion followed by an explicit reference conversion. In caso contrario, la conversione viene eseguita come conversione esplicita di un riferimento o conversione di identità.Otherwise, the conversion is executed as an explicit reference conversion or identity conversion.
  • Da un parametro di tipo U T, fornito T dipende da U (vincoli di parametro di tipo).From a type parameter U to T, provided T depends on U (Type parameter constraints). In fase di esecuzione, se U è un tipo di valore, T e U sono necessariamente dello stesso tipo e non viene eseguita alcuna conversione.At run-time, if U is a value type, then T and U are necessarily the same type and no conversion is performed. In caso contrario, se T è un tipo valore, la conversione viene eseguita come conversione unboxing.Otherwise, if T is a value type, the conversion is executed as an unboxing conversion. In caso contrario, la conversione viene eseguita come conversione esplicita di un riferimento o conversione di identità.Otherwise, the conversion is executed as an explicit reference conversion or identity conversion.

Se T è noto come tipo di riferimento, le conversioni precedenti vengono tutte classificate come conversioni esplicite dei riferimenti (conversioni esplicite dei riferimenti).If T is known to be a reference type, the conversions above are all classified as explicit reference conversions (Explicit reference conversions). Se T non è noto come tipo di riferimento, le conversioni precedenti vengono classificate come conversioni unboxing (conversioneunboxing).If T is not known to be a reference type, the conversions above are classified as unboxing conversions (Unboxing conversions).

Le regole precedenti non consentono una conversione esplicita diretta da un parametro di tipo non vincolato a un tipo non di interfaccia, che potrebbe essere sorprendente.The above rules do not permit a direct explicit conversion from an unconstrained type parameter to a non-interface type, which might be surprising. Il motivo di questa regola è impedire confusione e rendere chiara la semantica di tali conversioni.The reason for this rule is to prevent confusion and make the semantics of such conversions clear. Si consideri ad esempio la seguente dichiarazione:For example, consider the following declaration:

class X<T>
{
    public static long F(T t) {
        return (long)t;                // Error 
    }
}

Se è stata consentita la conversione diretta esplicita di t in int, è possibile che X<int>.F(7) restituisca 7L.If the direct explicit conversion of t to int were permitted, one might easily expect that X<int>.F(7) would return 7L. Tuttavia, non lo sarebbe, perché le conversioni numeriche standard vengono considerate solo quando i tipi sono noti come numerici in fase di binding.However, it would not, because the standard numeric conversions are only considered when the types are known to be numeric at binding-time. Per chiarire la semantica, è necessario scrivere l'esempio precedente:In order to make the semantics clear, the above example must instead be written:

class X<T>
{
    public static long F(T t) {
        return (long)(object)t;        // Ok, but will only work when T is long
    }
}

Questo codice verrà ora compilato, ma l'esecuzione di X<int>.F(7) genererebbe un'eccezione in fase di esecuzione, poiché non è possibile convertire una int boxed direttamente in un long.This code will now compile but executing X<int>.F(7) would then throw an exception at run-time, since a boxed int cannot be converted directly to a long.

Conversioni esplicite definite dall'utenteUser-defined explicit conversions

Una conversione esplicita definita dall'utente è costituita da una conversione esplicita standard facoltativa, seguita dall'esecuzione di un operatore di conversione esplicito o implicito definito dall'utente, seguita da un'altra conversione esplicita standard facoltativa.A user-defined explicit conversion consists of an optional standard explicit conversion, followed by execution of a user-defined implicit or explicit conversion operator, followed by another optional standard explicit conversion. Le regole esatte per la valutazione delle conversioni esplicite definite dall'utente sono descritte in elaborazione di conversioni esplicite definite dall'utente.The exact rules for evaluating user-defined explicit conversions are described in Processing of user-defined explicit conversions.

Conversioni standardStandard conversions

Le conversioni standard sono quelle predefinite che possono verificarsi come parte di una conversione definita dall'utente.The standard conversions are those pre-defined conversions that can occur as part of a user-defined conversion.

Conversioni implicite standardStandard implicit conversions

Le conversioni implicite seguenti sono classificate come conversioni implicite standard:The following implicit conversions are classified as standard implicit conversions:

Le conversioni implicite standard escludono in modo specifico le conversioni implicite definite dall'utente.The standard implicit conversions specifically exclude user-defined implicit conversions.

Conversioni esplicite standardStandard explicit conversions

Le conversioni esplicite standard sono tutte conversioni implicite standard e il subset delle conversioni esplicite per le quali esiste una conversione implicita standard opposta.The standard explicit conversions are all standard implicit conversions plus the subset of the explicit conversions for which an opposite standard implicit conversion exists. In altre parole, se esiste una conversione implicita standard da un tipo A a un tipo B, una conversione esplicita standard esiste dal tipo A al tipo B e dal tipo B al tipo A.In other words, if a standard implicit conversion exists from a type A to a type B, then a standard explicit conversion exists from type A to type B and from type B to type A.

Conversioni definite dall'utenteUser-defined conversions

C#consente di aumentare le conversioni implicite ed esplicite predefinite in base alle conversioni definite dall'utente.C# allows the pre-defined implicit and explicit conversions to be augmented by user-defined conversions. Le conversioni definite dall'utente vengono introdotte dichiarando operatori di conversione (operatori di conversione) in tipi di classe e struct.User-defined conversions are introduced by declaring conversion operators (Conversion operators) in class and struct types.

Conversioni definite dall'utente consentitePermitted user-defined conversions

C#consente di dichiarare solo determinate conversioni definite dall'utente.C# permits only certain user-defined conversions to be declared. In particolare, non è possibile ridefinire una conversione implicita o esplicita già esistente.In particular, it is not possible to redefine an already existing implicit or explicit conversion.

Per un tipo di origine specificato S e il tipo di destinazione T, se S o T sono tipi nullable, consentire a S0 e T0 di fare riferimento ai tipi sottostanti, in caso contrario S0 e T0 sono uguali a S e T rispettivamente.For a given source type S and target type T, if S or T are nullable types, let S0 and T0 refer to their underlying types, otherwise S0 and T0 are equal to S and T respectively. Una classe o uno struct è autorizzato a dichiarare una conversione da un tipo di origine S a un tipo di destinazione T solo se si verificano tutte le condizioni seguenti:A class or struct is permitted to declare a conversion from a source type S to a target type T only if all of the following are true:

  • S0 e T0 sono tipi diversi.S0 and T0 are different types.
  • S0 o T0 è il tipo di classe o struct in cui si verifica la dichiarazione di operatore.Either S0 or T0 is the class or struct type in which the operator declaration takes place.
  • S0T0 sono INTERFACE_TYPE.Neither S0 nor T0 is an interface_type.
  • Escludendo le conversioni definite dall'utente, non esiste una conversione da S a T o da T a S.Excluding user-defined conversions, a conversion does not exist from S to T or from T to S.

Le restrizioni che si applicano alle conversioni definite dall'utente vengono descritte ulteriormente negli operatori di conversione.The restrictions that apply to user-defined conversions are discussed further in Conversion operators.

Operatori di conversione accuratiLifted conversion operators

Dato un operatore di conversione definito dall'utente che converte da un tipo di valore non nullable S a un tipo di valore non nullable T, esiste un operatore di conversione accurato che converte da S? a T?.Given a user-defined conversion operator that converts from a non-nullable value type S to a non-nullable value type T, a lifted conversion operator exists that converts from S? to T?. Questo operatore di conversione Lift esegue l'annullamento del wrapping da S? a S seguito dalla conversione definita dall'utente da S a T seguito da un wrapping da T a T?, ad eccezione del fatto che un valore null S? viene convertito direttamente in un T?con valori null.This lifted conversion operator performs an unwrapping from S? to S followed by the user-defined conversion from S to T followed by a wrapping from T to T?, except that a null valued S? converts directly to a null valued T?.

Un operatore di conversione Lift ha la stessa classificazione implicita o esplicita dell'operatore di conversione definito dall'utente sottostante.A lifted conversion operator has the same implicit or explicit classification as its underlying user-defined conversion operator. Il termine "conversione definita dall'utente" si applica all'utilizzo di operatori di conversione sia definiti dall'utente che rimossi.The term "user-defined conversion" applies to the use of both user-defined and lifted conversion operators.

Valutazione delle conversioni definite dall'utenteEvaluation of user-defined conversions

Una conversione definita dall'utente converte un valore dal tipo, denominato tipo di origine, a un altro tipo, denominato tipo di destinazione.A user-defined conversion converts a value from its type, called the source type, to another type, called the target type. Valutazione di un centro di conversione definito dall'utente per la ricerca dell'operatore di conversione definito dall'utente più specifico per i tipi di origine e di destinazione specifici.Evaluation of a user-defined conversion centers on finding the most specific user-defined conversion operator for the particular source and target types. Questa determinazione è suddivisa in diversi passaggi:This determination is broken into several steps:

  • Ricerca del set di classi e struct da cui verranno considerati gli operatori di conversione definiti dall'utente.Finding the set of classes and structs from which user-defined conversion operators will be considered. Questo set è costituito dal tipo di origine e dalle relative classi base e dal tipo di destinazione e dalle relative classi di base (con i presupposti impliciti che solo classi e struct possono dichiarare operatori definiti dall'utente e che i tipi non di classe non hanno classi base).This set consists of the source type and its base classes and the target type and its base classes (with the implicit assumptions that only classes and structs can declare user-defined operators, and that non-class types have no base classes). Ai fini di questo passaggio, se il tipo di origine o di destinazione è un nullable_type, viene invece utilizzato il tipo sottostante.For the purposes of this step, if either the source or target type is a nullable_type, their underlying type is used instead.
  • Da tale set di tipi, che determina quali operatori di conversione definiti dall'utente e rimossi sono applicabili.From that set of types, determining which user-defined and lifted conversion operators are applicable. Affinché un operatore di conversione sia applicabile, deve essere possibile eseguire una conversione standard (conversioni standard) dal tipo di origine al tipo di operando dell'operatore e deve essere possibile eseguire una conversione standard dal tipo di risultato dell'operatore al tipo di destinazione.For a conversion operator to be applicable, it must be possible to perform a standard conversion (Standard conversions) from the source type to the operand type of the operator, and it must be possible to perform a standard conversion from the result type of the operator to the target type.
  • Dal set di operatori definiti dall'utente applicabili, che determinano l'operatore che non è ambiguamente più specifico.From the set of applicable user-defined operators, determining which operator is unambiguously the most specific. In termini generali, l'operatore più specifico è l'operatore il cui tipo di operando è "più vicino" al tipo di origine e il cui tipo di risultato è "più vicino" al tipo di destinazione.In general terms, the most specific operator is the operator whose operand type is "closest" to the source type and whose result type is "closest" to the target type. Gli operatori di conversione definiti dall'utente sono preferiti rispetto agli operatori di conversione rimossi.User-defined conversion operators are preferred over lifted conversion operators. Nelle sezioni seguenti vengono definite le regole esatte per la definizione dell'operatore di conversione definito dall'utente più specifico.The exact rules for establishing the most specific user-defined conversion operator are defined in the following sections.

Una volta identificato un operatore di conversione definito dall'utente più specifico, l'esecuzione effettiva della conversione definita dall'utente prevede fino a tre passaggi:Once a most specific user-defined conversion operator has been identified, the actual execution of the user-defined conversion involves up to three steps:

  • Prima di tutto, se necessario, eseguire una conversione standard dal tipo di origine al tipo di operando dell'operatore di conversione definito dall'utente o lifted.First, if required, performing a standard conversion from the source type to the operand type of the user-defined or lifted conversion operator.
  • Richiamando quindi l'operatore di conversione definito dall'utente o lifted per eseguire la conversione.Next, invoking the user-defined or lifted conversion operator to perform the conversion.
  • Infine, se necessario, l'esecuzione di una conversione standard dal tipo di risultato dell'operatore di conversione definito dall'utente o lifted al tipo di destinazione.Finally, if required, performing a standard conversion from the result type of the user-defined or lifted conversion operator to the target type.

La valutazione di una conversione definita dall'utente non prevede mai più di un operatore di conversione definito dall'utente o lifted.Evaluation of a user-defined conversion never involves more than one user-defined or lifted conversion operator. In altre parole, una conversione dal tipo S al tipo T non eseguirà mai prima una conversione definita dall'utente da S a X e quindi eseguirà una conversione definita dall'utente da X a T.In other words, a conversion from type S to type T will never first execute a user-defined conversion from S to X and then execute a user-defined conversion from X to T.

Nelle sezioni seguenti vengono fornite le definizioni esatte della valutazione delle conversioni esplicite o implicite definite dall'utente.Exact definitions of evaluation of user-defined implicit or explicit conversions are given in the following sections. Le definizioni utilizzano i termini seguenti:The definitions make use of the following terms:

  • Se una conversione implicita standard (conversioni implicite standard) esiste da un tipo A a un tipo Be se nessuna delle due AB sono interface_types, A viene detto che è incluso Be B viene detto che comprende A.If a standard implicit conversion (Standard implicit conversions) exists from a type A to a type B, and if neither A nor B are interface_types, then A is said to be encompassed by B, and B is said to encompass A.
  • Il tipo più incluso in un set di tipi è quello che comprende tutti gli altri tipi nel set.The most encompassing type in a set of types is the one type that encompasses all other types in the set. Se nessun tipo singolo include tutti gli altri tipi, il set non include il tipo più incluso.If no single type encompasses all other types, then the set has no most encompassing type. In termini più intuitivi, il tipo più comprendente è il tipo "più grande" nel set, ovvero quello in cui ogni altro tipo può essere convertito in modo implicito.In more intuitive terms, the most encompassing type is the "largest" type in the set—the one type to which each of the other types can be implicitly converted.
  • Il tipo più incluso in un set di tipi è quello incluso in tutti gli altri tipi del set.The most encompassed type in a set of types is the one type that is encompassed by all other types in the set. Se nessun tipo singolo è incluso in tutti gli altri tipi, il set non ha un tipo più incluso.If no single type is encompassed by all other types, then the set has no most encompassed type. In termini più intuitivi, il tipo più incluso è il tipo "più piccolo" nel set, ovvero quello che può essere convertito in modo implicito in ognuno degli altri tipi.In more intuitive terms, the most encompassed type is the "smallest" type in the set—the one type that can be implicitly converted to each of the other types.

Elaborazione delle conversioni implicite definite dall'utenteProcessing of user-defined implicit conversions

Una conversione implicita definita dall'utente dal tipo S al tipo T viene elaborata come indicato di seguito:A user-defined implicit conversion from type S to type T is processed as follows:

  • Determinare i tipi S0 e T0.Determine the types S0 and T0. Se S o T sono tipi nullable, S0 e T0 sono i tipi sottostanti, in caso contrario S0 e T0 sono uguali a S e T rispettivamente.If S or T are nullable types, S0 and T0 are their underlying types, otherwise S0 and T0 are equal to S and T respectively.
  • Trovare il set di tipi, D, da cui verranno considerati gli operatori di conversione definiti dall'utente.Find the set of types, D, from which user-defined conversion operators will be considered. Questo set è costituito da S0 (se S0 è una classe o uno struct), le classi di base di S0 (se S0 è una classe) e T0 (se T0 è una classe o uno struct).This set consists of S0 (if S0 is a class or struct), the base classes of S0 (if S0 is a class), and T0 (if T0 is a class or struct).
  • Trovare il set di operatori di conversione rimossi e definiti dall'utente applicabili U.Find the set of applicable user-defined and lifted conversion operators, U. Questo set è costituito dagli operatori di conversione impliciti definiti dall'utente e rimossi dichiarati dalle classi o dagli struct in D che convertono da un tipo che comprende S a un tipo incluso in T.This set consists of the user-defined and lifted implicit conversion operators declared by the classes or structs in D that convert from a type encompassing S to a type encompassed by T. Se U è vuoto, la conversione non è definita e si verifica un errore in fase di compilazione.If U is empty, the conversion is undefined and a compile-time error occurs.
  • Trovare il tipo di origine più specifico, SX, degli operatori in U:Find the most specific source type, SX, of the operators in U:
    • Se uno degli operatori di U converte da S, SX S.If any of the operators in U convert from S, then SX is S.
    • In caso contrario, SX è il tipo più incluso nel set combinato di tipi di origine degli operatori U.Otherwise, SX is the most encompassed type in the combined set of source types of the operators in U. Se non è possibile trovare esattamente un tipo più incluso, la conversione è ambigua e si verifica un errore in fase di compilazione.If exactly one most encompassed type cannot be found, then the conversion is ambiguous and a compile-time error occurs.
  • Trovare il tipo di destinazione più specifico, TX, degli operatori in U:Find the most specific target type, TX, of the operators in U:
    • Se uno degli operatori di U converte in T, TX è T.If any of the operators in U convert to T, then TX is T.
    • In caso contrario, TX è il tipo più incluso nel set combinato di tipi di destinazione degli operatori nella U.Otherwise, TX is the most encompassing type in the combined set of target types of the operators in U. Se non è possibile trovare esattamente un tipo più onnicomprensivo, la conversione è ambigua e si verifica un errore in fase di compilazione.If exactly one most encompassing type cannot be found, then the conversion is ambiguous and a compile-time error occurs.
  • Trovare l'operatore di conversione più specifico:Find the most specific conversion operator:
    • Se U contiene esattamente un operatore di conversione definito dall'utente che converte da SX a TX, si tratta dell'operatore di conversione più specifico.If U contains exactly one user-defined conversion operator that converts from SX to TX, then this is the most specific conversion operator.
    • In caso contrario, se U contiene esattamente un operatore di conversione lifted che converte da SX a TX, si tratta dell'operatore di conversione più specifico.Otherwise, if U contains exactly one lifted conversion operator that converts from SX to TX, then this is the most specific conversion operator.
    • In caso contrario, la conversione è ambigua e si verifica un errore in fase di compilazione.Otherwise, the conversion is ambiguous and a compile-time error occurs.
  • Infine, applicare la conversione:Finally, apply the conversion:
    • Se S non è SX, viene eseguita una conversione implicita standard da S a SX.If S is not SX, then a standard implicit conversion from S to SX is performed.
    • Viene richiamato l'operatore di conversione più specifico per eseguire la conversione da SX a TX.The most specific conversion operator is invoked to convert from SX to TX.
    • Se TX non è T, viene eseguita una conversione implicita standard da TX a T.If TX is not T, then a standard implicit conversion from TX to T is performed.

Elaborazione delle conversioni esplicite definite dall'utenteProcessing of user-defined explicit conversions

Una conversione esplicita definita dall'utente dal tipo S al tipo T viene elaborata come indicato di seguito:A user-defined explicit conversion from type S to type T is processed as follows:

  • Determinare i tipi S0 e T0.Determine the types S0 and T0. Se S o T sono tipi nullable, S0 e T0 sono i tipi sottostanti, in caso contrario S0 e T0 sono uguali a S e T rispettivamente.If S or T are nullable types, S0 and T0 are their underlying types, otherwise S0 and T0 are equal to S and T respectively.
  • Trovare il set di tipi, D, da cui verranno considerati gli operatori di conversione definiti dall'utente.Find the set of types, D, from which user-defined conversion operators will be considered. Questo set è costituito da S0 (se S0 è una classe o uno struct), le classi di base di S0 (se S0 è una classe), T0 (se T0 è una classe o uno struct) e le classi di base di T0 (se T0 è una classe).This set consists of S0 (if S0 is a class or struct), the base classes of S0 (if S0 is a class), T0 (if T0 is a class or struct), and the base classes of T0 (if T0 is a class).
  • Trovare il set di operatori di conversione rimossi e definiti dall'utente applicabili U.Find the set of applicable user-defined and lifted conversion operators, U. Questo set è costituito dagli operatori di conversione espliciti o impliciti definiti dall'utente e rimossi dichiarati dalle classi o dagli struct in D che convertono da un tipo incluso o incluso S a un tipo che comprende o è incluso in T.This set consists of the user-defined and lifted implicit or explicit conversion operators declared by the classes or structs in D that convert from a type encompassing or encompassed by S to a type encompassing or encompassed by T. Se U è vuoto, la conversione non è definita e si verifica un errore in fase di compilazione.If U is empty, the conversion is undefined and a compile-time error occurs.
  • Trovare il tipo di origine più specifico, SX, degli operatori in U:Find the most specific source type, SX, of the operators in U:
    • Se uno degli operatori di U converte da S, SX S.If any of the operators in U convert from S, then SX is S.
    • In caso contrario, se uno degli operatori di U converte da tipi che includono S, SX è il tipo più incluso nel set combinato di tipi di origine di tali operatori.Otherwise, if any of the operators in U convert from types that encompass S, then SX is the most encompassed type in the combined set of source types of those operators. Se non è possibile trovare un tipo più incluso, la conversione è ambigua e si verifica un errore in fase di compilazione.If no most encompassed type can be found, then the conversion is ambiguous and a compile-time error occurs.
    • In caso contrario, SX è il tipo più incluso nel set combinato di tipi di origine degli operatori U.Otherwise, SX is the most encompassing type in the combined set of source types of the operators in U. Se non è possibile trovare esattamente un tipo più onnicomprensivo, la conversione è ambigua e si verifica un errore in fase di compilazione.If exactly one most encompassing type cannot be found, then the conversion is ambiguous and a compile-time error occurs.
  • Trovare il tipo di destinazione più specifico, TX, degli operatori in U:Find the most specific target type, TX, of the operators in U:
    • Se uno degli operatori di U converte in T, TX è T.If any of the operators in U convert to T, then TX is T.
    • In caso contrario, se uno degli operatori di U converte in tipi inclusi da T, TX è il tipo più incluso nel set combinato di tipi di destinazione di tali operatori.Otherwise, if any of the operators in U convert to types that are encompassed by T, then TX is the most encompassing type in the combined set of target types of those operators. Se non è possibile trovare esattamente un tipo più onnicomprensivo, la conversione è ambigua e si verifica un errore in fase di compilazione.If exactly one most encompassing type cannot be found, then the conversion is ambiguous and a compile-time error occurs.
    • In caso contrario, TX è il tipo più incluso nel set combinato di tipi di destinazione degli operatori U.Otherwise, TX is the most encompassed type in the combined set of target types of the operators in U. Se non è possibile trovare un tipo più incluso, la conversione è ambigua e si verifica un errore in fase di compilazione.If no most encompassed type can be found, then the conversion is ambiguous and a compile-time error occurs.
  • Trovare l'operatore di conversione più specifico:Find the most specific conversion operator:
    • Se U contiene esattamente un operatore di conversione definito dall'utente che converte da SX a TX, si tratta dell'operatore di conversione più specifico.If U contains exactly one user-defined conversion operator that converts from SX to TX, then this is the most specific conversion operator.
    • In caso contrario, se U contiene esattamente un operatore di conversione lifted che converte da SX a TX, si tratta dell'operatore di conversione più specifico.Otherwise, if U contains exactly one lifted conversion operator that converts from SX to TX, then this is the most specific conversion operator.
    • In caso contrario, la conversione è ambigua e si verifica un errore in fase di compilazione.Otherwise, the conversion is ambiguous and a compile-time error occurs.
  • Infine, applicare la conversione:Finally, apply the conversion:
    • Se S non è SX, viene eseguita una conversione esplicita standard da S a SX.If S is not SX, then a standard explicit conversion from S to SX is performed.
    • Viene richiamato l'operatore di conversione più specifico definito dall'utente per eseguire la conversione da SX a TX.The most specific user-defined conversion operator is invoked to convert from SX to TX.
    • Se TX non è T, viene eseguita una conversione esplicita standard da TX a T.If TX is not T, then a standard explicit conversion from TX to T is performed.

Conversioni di funzioni anonimeAnonymous function conversions

Un anonymous_method_expression o un lambda_expression è classificato come funzione anonima (espressioni di funzione anonime).An anonymous_method_expression or lambda_expression is classified as an anonymous function (Anonymous function expressions). L'espressione non ha un tipo, ma può essere convertita in modo implicito in un tipo di delegato o di albero delle espressioni compatibile.The expression does not have a type but can be implicitly converted to a compatible delegate type or expression tree type. In particolare, una funzione anonima F è compatibile con un tipo delegato D fornito:Specifically, an anonymous function F is compatible with a delegate type D provided:

  • Se F contiene un anonymous_function_signature, D e F hanno lo stesso numero di parametri.If F contains an anonymous_function_signature, then D and F have the same number of parameters.
  • Se F non contiene un anonymous_function_signature, D può avere zero o più parametri di qualsiasi tipo, a condizione che nessun parametro di D abbia il modificatore di parametro out.If F does not contain an anonymous_function_signature, then D may have zero or more parameters of any type, as long as no parameter of D has the out parameter modifier.
  • Se F dispone di un elenco di parametri tipizzato in modo esplicito, ogni parametro in D ha lo stesso tipo e modificatori del parametro corrispondente in F.If F has an explicitly typed parameter list, each parameter in D has the same type and modifiers as the corresponding parameter in F.
  • Se F dispone di un elenco di parametri tipizzato in modo implicito, D non dispone di parametri ref o out.If F has an implicitly typed parameter list, D has no ref or out parameters.
  • Se il corpo di F è un'espressione e D dispone di un tipo restituito void o F è async e D ha il tipo restituito Task, quando a ogni parametro di F viene assegnato il tipo del parametro corrispondente in D, il corpo di F è un'espressione valida ( espressioniWRT) che verrebbe consentita come statement_expression (istruzioni Expression).If the body of F is an expression, and either D has a void return type or F is async and D has the return type Task, then when each parameter of F is given the type of the corresponding parameter in D, the body of F is a valid expression (wrt Expressions) that would be permitted as a statement_expression (Expression statements).
  • Se il corpo di F è un blocco di istruzioni e D dispone di un tipo restituito void o F è async e D ha il tipo restituito Task, quando a ogni parametro di F viene assegnato il tipo del parametro corrispondente in D, il corpo di F è un blocco di istruzione valido ( blocchiWRT) in cui nessuna istruzione return specifica un'espressione.If the body of F is a statement block, and either D has a void return type or F is async and D has the return type Task, then when each parameter of F is given the type of the corresponding parameter in D, the body of F is a valid statement block (wrt Blocks) in which no return statement specifies an expression.
  • Se il corpo di F è un'espressione e F è non asincrono e D ha un tipo restituito non void To F è async e D ha un tipo restituito Task<T>, quando a ogni parametro di F viene assegnato il tipo del parametro corrispondente in D, il corpo di F è un'espressione valida ( espressioniWRT) convertibile in modo implicito in T.If the body of F is an expression, and either F is non-async and D has a non-void return type T, or F is async and D has a return type Task<T>, then when each parameter of F is given the type of the corresponding parameter in D, the body of F is a valid expression (wrt Expressions) that is implicitly convertible to T.
  • Se il corpo di F è un blocco di istruzioni e F è non asincrono e D ha un tipo restituito non void T, o F è async e D dispone di un tipo restituito Task<T>, quindi quando ogni parametro di F viene assegnato il tipo del parametro corrispondente in D, il corpo di F è un blocco di istruzioni valido ( blocchiWRT) con un punto finale non raggiungibile in cui ogni istruzione return specifica un'espressione convertibile in modo implicito in T.If the body of F is a statement block, and either F is non-async and D has a non-void return type T, or F is async and D has a return type Task<T>, then when each parameter of F is given the type of the corresponding parameter in D, the body of F is a valid statement block (wrt Blocks) with a non-reachable end point in which each return statement specifies an expression that is implicitly convertible to T.

Per motivi di brevità, in questa sezione viene utilizzata la forma breve per i tipi di attività Task e Task<T> (funzioni asincrone).For the purpose of brevity, this section uses the short form for the task types Task and Task<T> (Async functions).

Un'espressione lambda F è compatibile con un tipo di albero delle espressioni Expression<D> se F è compatibile con il tipo di delegato D.A lambda expression F is compatible with an expression tree type Expression<D> if F is compatible with the delegate type D. Si noti che questa operazione non si applica ai metodi anonimi, ma solo alle espressioni lambda.Note that this does not apply to anonymous methods, only lambda expressions.

Alcune espressioni lambda non possono essere convertite in tipi di albero delle espressioni: anche se la conversione esiste, l'operazione non riesce in fase di compilazione.Certain lambda expressions cannot be converted to expression tree types: Even though the conversion exists, it fails at compile-time. Questa situazione si verifica se l'espressione lambda:This is the case if the lambda expression:

  • Ha un corpo del bloccoHas a block body
  • Contiene operatori di assegnazione semplici o compostiContains simple or compound assignment operators
  • Contiene un'espressione associata dinamicamenteContains a dynamically bound expression
  • AsincronoIs async

Gli esempi seguenti usano un tipo delegato generico Func<A,R> che rappresenta una funzione che accetta un argomento di tipo A e restituisce un valore di tipo R:The examples that follow use a generic delegate type Func<A,R> which represents a function that takes an argument of type A and returns a value of type R:

delegate R Func<A,R>(A arg);

Nelle assegnazioniIn the assignments

Func<int,int> f1 = x => x + 1;                 // Ok

Func<int,double> f2 = x => x + 1;              // Ok

Func<double,int> f3 = x => x + 1;              // Error

Func<int, Task<int>> f4 = async x => x + 1;    // Ok

il parametro e i tipi restituiti di ogni funzione anonima sono determinati dal tipo della variabile a cui è assegnata la funzione anonima.the parameter and return types of each anonymous function are determined from the type of the variable to which the anonymous function is assigned.

La prima assegnazione converte correttamente la funzione anonima nel tipo delegato Func<int,int> perché, quando x viene assegnato il tipo int, x+1 è un'espressione valida convertibile in modo implicito nel tipo int.The first assignment successfully converts the anonymous function to the delegate type Func<int,int> because, when x is given type int, x+1 is a valid expression that is implicitly convertible to type int.

Analogamente, la seconda assegnazione converte correttamente la funzione anonima nel tipo delegato Func<int,double> perché il risultato di x+1 (di tipo int) è convertibile in modo implicito nel tipo double.Likewise, the second assignment successfully converts the anonymous function to the delegate type Func<int,double> because the result of x+1 (of type int) is implicitly convertible to type double.

Tuttavia, la terza assegnazione è un errore in fase di compilazione perché, quando x viene assegnato il tipo double, il risultato di x+1 (di tipo double) non è convertibile in modo implicito nel tipo int.However, the third assignment is a compile-time error because, when x is given type double, the result of x+1 (of type double) is not implicitly convertible to type int.

La quarta assegnazione converte correttamente la funzione asincrona anonima nel tipo delegato Func<int, Task<int>> perché il risultato di x+1 (di tipo int) è convertibile in modo implicito nel tipo di risultato int del tipo di attività Task<int>.The fourth assignment successfully converts the anonymous async function to the delegate type Func<int, Task<int>> because the result of x+1 (of type int) is implicitly convertible to the result type int of the task type Task<int>.

Le funzioni anonime possono influenzare la risoluzione dell'overload e partecipare all'inferenza del tipo.Anonymous functions may influence overload resolution, and participate in type inference. Per ulteriori informazioni, vedere membri di funzione .See Function members for further details.

Valutazione delle conversioni di funzioni anonime nei tipi delegatiEvaluation of anonymous function conversions to delegate types

La conversione di una funzione anonima in un tipo delegato produce un'istanza di delegato che fa riferimento alla funzione anonima e al set di variabili esterne acquisite (possibilmente vuote) attive al momento della valutazione.Conversion of an anonymous function to a delegate type produces a delegate instance which references the anonymous function and the (possibly empty) set of captured outer variables that are active at the time of the evaluation. Quando il delegato viene richiamato, viene eseguito il corpo della funzione anonima.When the delegate is invoked, the body of the anonymous function is executed. Il codice nel corpo viene eseguito utilizzando il set di variabili esterne acquisite a cui fa riferimento il delegato.The code in the body is executed using the set of captured outer variables referenced by the delegate.

L'elenco chiamate di un delegato prodotto da una funzione anonima contiene una singola voce.The invocation list of a delegate produced from an anonymous function contains a single entry. L'oggetto di destinazione esatto e il metodo di destinazione del delegato non sono specificati.The exact target object and target method of the delegate are unspecified. In particolare, non viene specificato se l'oggetto di destinazione del delegato è null, il valore this del membro della funzione contenitore o un altro oggetto.In particular, it is unspecified whether the target object of the delegate is null, the this value of the enclosing function member, or some other object.

Le conversioni di funzioni anonime semanticamente identiche con lo stesso set (possibilmente vuoto) di istanze di variabili esterne acquisite agli stessi tipi delegati sono consentite (ma non necessarie) per restituire la stessa istanza del delegato.Conversions of semantically identical anonymous functions with the same (possibly empty) set of captured outer variable instances to the same delegate types are permitted (but not required) to return the same delegate instance. Il termine semanticamente identico viene usato qui per indicare che l'esecuzione delle funzioni anonime, in tutti i casi, produce gli stessi effetti dato gli stessi argomenti.The term semantically identical is used here to mean that execution of the anonymous functions will, in all cases, produce the same effects given the same arguments. Questa regola consente di ottimizzare il codice come il seguente.This rule permits code such as the following to be optimized.

delegate double Function(double x);

class Test
{
    static double[] Apply(double[] a, Function f) {
        double[] result = new double[a.Length];
        for (int i = 0; i < a.Length; i++) result[i] = f(a[i]);
        return result;
    }

    static void F(double[] a, double[] b) {
        a = Apply(a, (double x) => Math.Sin(x));
        b = Apply(b, (double y) => Math.Sin(y));
        ...
    }
}

Poiché i due delegati di funzione anonima hanno lo stesso set (vuoto) di variabili esterne acquisite e poiché le funzioni anonime sono semanticamente identiche, il compilatore può fare riferimento allo stesso metodo di destinazione.Since the two anonymous function delegates have the same (empty) set of captured outer variables, and since the anonymous functions are semantically identical, the compiler is permitted to have the delegates refer to the same target method. Il compilatore può effettivamente restituire la stessa istanza del delegato da entrambe le espressioni di funzioni anonime.Indeed, the compiler is permitted to return the very same delegate instance from both anonymous function expressions.

Valutazione delle conversioni di funzioni anonime nei tipi di albero delle espressioniEvaluation of anonymous function conversions to expression tree types

La conversione di una funzione anonima in un tipo di albero delle espressioni genera un albero delle espressioni (tipi di albero delle espressioni).Conversion of an anonymous function to an expression tree type produces an expression tree (Expression tree types). Più precisamente, la valutazione della conversione di funzione anonima comporta la costruzione di una struttura di oggetti che rappresenta la struttura della funzione anonima stessa.More precisely, evaluation of the anonymous function conversion leads to the construction of an object structure that represents the structure of the anonymous function itself. La struttura precisa dell'albero delle espressioni e il processo esatto per crearla sono definite dall'implementazione.The precise structure of the expression tree, as well as the exact process for creating it, are implementation defined.

Esempio di implementazioneImplementation example

In questa sezione viene descritta una possibile implementazione di conversioni di funzioni anonime in C# termini di altri costrutti.This section describes a possible implementation of anonymous function conversions in terms of other C# constructs. L'implementazione descritta di seguito si basa sugli stessi principi usati dal compilatore Microsoft C# , ma non è un'implementazione obbligatoria, né è l'unico possibile.The implementation described here is based on the same principles used by the Microsoft C# compiler, but it is by no means a mandated implementation, nor is it the only one possible. Indica solo brevemente le conversioni agli alberi delle espressioni, perché la semantica esatta esula dall'ambito di questa specifica.It only briefly mentions conversions to expression trees, as their exact semantics are outside the scope of this specification.

Nella parte restante di questa sezione vengono forniti alcuni esempi di codice che contengono funzioni anonime con caratteristiche diverse.The remainder of this section gives several examples of code that contains anonymous functions with different characteristics. Per ogni esempio, viene fornita una traduzione corrispondente al codice che usa C# solo altri costrutti.For each example, a corresponding translation to code that uses only other C# constructs is provided. Negli esempi, l'identificatore D si presuppone che rappresenti il tipo delegato seguente:In the examples, the identifier D is assumed by represent the following delegate type:

public delegate void D();

La forma più semplice di una funzione anonima è quella che non acquisisce variabili esterne:The simplest form of an anonymous function is one that captures no outer variables:

class Test
{
    static void F() {
        D d = () => { Console.WriteLine("test"); };
    }
}

Questo può essere convertito in un'istanza di delegato che fa riferimento a un metodo statico generato dal compilatore in cui viene inserito il codice della funzione anonima:This can be translated to a delegate instantiation that references a compiler generated static method in which the code of the anonymous function is placed:

class Test
{
    static void F() {
        D d = new D(__Method1);
    }

    static void __Method1() {
        Console.WriteLine("test");
    }
}

Nell'esempio seguente la funzione anonima fa riferimento ai membri di istanza di this:In the following example, the anonymous function references instance members of this:

class Test
{
    int x;

    void F() {
        D d = () => { Console.WriteLine(x); };
    }
}

Questo può essere convertito in un metodo di istanza generato dal compilatore che contiene il codice della funzione anonima:This can be translated to a compiler generated instance method containing the code of the anonymous function:

class Test
{
    int x;

    void F() {
        D d = new D(__Method1);
    }

    void __Method1() {
        Console.WriteLine(x);
    }
}

In questo esempio, la funzione anonima acquisisce una variabile locale:In this example, the anonymous function captures a local variable:

class Test
{
    void F() {
        int y = 123;
        D d = () => { Console.WriteLine(y); };
    }
}

La durata della variabile locale deve ora essere estesa almeno alla durata del delegato della funzione anonima.The lifetime of the local variable must now be extended to at least the lifetime of the anonymous function delegate. Questa operazione può essere eseguita mediante il "sollevamento" della variabile locale in un campo di una classe generata dal compilatore.This can be achieved by "hoisting" the local variable into a field of a compiler generated class. La creazione di un'istanza della variabile locale (creazione di un'istanza di variabili locali) corrisponde quindi alla creazione di un'istanza della classe generata dal compilatore e l'accesso alla variabile locale corrisponde all'accesso a un campo nell'istanza della classe generata dal compilatore.Instantiation of the local variable (Instantiation of local variables) then corresponds to creating an instance of the compiler generated class, and accessing the local variable corresponds to accessing a field in the instance of the compiler generated class. Inoltre, la funzione anonima diventa un metodo di istanza della classe generata dal compilatore:Furthermore, the anonymous function becomes an instance method of the compiler generated class:

class Test
{
    void F() {
        __Locals1 __locals1 = new __Locals1();
        __locals1.y = 123;
        D d = new D(__locals1.__Method1);
    }

    class __Locals1
    {
        public int y;

        public void __Method1() {
            Console.WriteLine(y);
        }
    }
}

Infine, la funzione anonima seguente acquisisce this e due variabili locali con durate diverse:Finally, the following anonymous function captures this as well as two local variables with different lifetimes:

class Test
{
    int x;

    void F() {
        int y = 123;
        for (int i = 0; i < 10; i++) {
            int z = i * 2;
            D d = () => { Console.WriteLine(x + y + z); };
        }
    }
}

In questo caso viene creata una classe generata dal compilatore per ogni blocco di istruzioni in cui vengono acquisite le variabili locali in modo che le variabili locali nei diversi blocchi possano avere durate indipendenti.Here, a compiler generated class is created for each statement block in which locals are captured such that the locals in the different blocks can have independent lifetimes. Un'istanza di __Locals2, la classe generata dal compilatore per il blocco di istruzioni interno, contiene la variabile locale z e un campo che fa riferimento a un'istanza di __Locals1.An instance of __Locals2, the compiler generated class for the inner statement block, contains the local variable z and a field that references an instance of __Locals1. Un'istanza di __Locals1, la classe generata dal compilatore per il blocco di istruzioni esterno, contiene la variabile locale y e un campo che fa riferimento this del membro della funzione contenitore.An instance of __Locals1, the compiler generated class for the outer statement block, contains the local variable y and a field that references this of the enclosing function member. Con queste strutture di dati è possibile raggiungere tutte le variabili esterne acquisite tramite un'istanza di __Local2e il codice della funzione anonima può quindi essere implementato come metodo di istanza di quella classe.With these data structures it is possible to reach all captured outer variables through an instance of __Local2, and the code of the anonymous function can thus be implemented as an instance method of that class.

class Test
{
    void F() {
        __Locals1 __locals1 = new __Locals1();
        __locals1.__this = this;
        __locals1.y = 123;
        for (int i = 0; i < 10; i++) {
            __Locals2 __locals2 = new __Locals2();
            __locals2.__locals1 = __locals1;
            __locals2.z = i * 2;
            D d = new D(__locals2.__Method1);
        }
    }

    class __Locals1
    {
        public Test __this;
        public int y;
    }

    class __Locals2
    {
        public __Locals1 __locals1;
        public int z;

        public void __Method1() {
            Console.WriteLine(__locals1.__this.x + __locals1.y + z);
        }
    }
}

La stessa tecnica applicata qui per acquisire le variabili locali può essere usata anche durante la conversione di funzioni anonime in alberi delle espressioni: i riferimenti agli oggetti generati dal compilatore possono essere archiviati nell'albero delle espressioni e l'accesso alle variabili locali può essere rappresentati come accessi al campo su questi oggetti.The same technique applied here to capture local variables can also be used when converting anonymous functions to expression trees: References to the compiler generated objects can be stored in the expression tree, and access to the local variables can be represented as field accesses on these objects. Il vantaggio di questo approccio è che consente di condividere le variabili locali "elevate" tra i delegati e gli alberi delle espressioni.The advantage of this approach is that it allows the "lifted" local variables to be shared between delegates and expression trees.

Conversioni di gruppi di metodiMethod group conversions

Una conversione implicita (conversioni implicite) esiste da un gruppo di metodi (classificazioni di espressioni) a un tipo delegato compatibile.An implicit conversion (Implicit conversions) exists from a method group (Expression classifications) to a compatible delegate type. Dato un tipo di delegato D e un'espressione E classificata come un gruppo di metodi, esiste una conversione implicita da E a D se E contiene almeno un metodo applicabile nel formato normale (membro dellafunzione applicabile) a un elenco di argomenti costruito usando i tipi di parametro e i modificatori di D, come descritto di seguito.Given a delegate type D and an expression E that is classified as a method group, an implicit conversion exists from E to D if E contains at least one method that is applicable in its normal form (Applicable function member) to an argument list constructed by use of the parameter types and modifiers of D, as described in the following.

L'applicazione in fase di compilazione di una conversione da un gruppo di metodi E a un tipo delegato D è descritta nell'esempio seguente.The compile-time application of a conversion from a method group E to a delegate type D is described in the following. Si noti che l'esistenza di una conversione implicita da E a D non garantisce che l'applicazione della conversione in fase di compilazione avrà esito positivo senza errori.Note that the existence of an implicit conversion from E to D does not guarantee that the compile-time application of the conversion will succeed without error.

  • Viene selezionato un solo metodo M corrispondente a una chiamata al metodo (chiamate al metodo) del form E(A), con le modifiche seguenti:A single method M is selected corresponding to a method invocation (Method invocations) of the form E(A), with the following modifications:
    • L'elenco di argomenti A è un elenco di espressioni, ciascuna classificata come variabile e con il tipo e il modificatore (ref o out) del parametro corrispondente nell' formal_parameter_list di D.The argument list A is a list of expressions, each classified as a variable and with the type and modifier (ref or out) of the corresponding parameter in the formal_parameter_list of D.
    • I metodi candidati considerati sono solo quelli applicabili nel formato normale (membro della funzione applicabile), non quelli applicabili solo nel formato espanso.The candidate methods considered are only those methods that are applicable in their normal form (Applicable function member), not those applicable only in their expanded form.
  • Se l'algoritmo delle chiamate di metodo genera un errore, si verifica un errore in fase di compilazione.If the algorithm of Method invocations produces an error, then a compile-time error occurs. In caso contrario, l'algoritmo produce un unico metodo migliore M avere lo stesso numero di parametri D e la conversione viene considerata esistente.Otherwise the algorithm produces a single best method M having the same number of parameters as D and the conversion is considered to exist.
  • Il M del metodo selezionato deve essere compatibile (la compatibilità con idelegati) con il tipo delegato D. in caso contrario, si verifica un errore in fase di compilazione.The selected method M must be compatible (Delegate compatibility) with the delegate type D, or otherwise, a compile-time error occurs.
  • Se il metodo selezionato M è un metodo di istanza, l'espressione dell'istanza associata a E determina l'oggetto di destinazione del delegato.If the selected method M is an instance method, the instance expression associated with E determines the target object of the delegate.
  • Se il metodo selezionato M è un metodo di estensione che è indicato tramite un accesso a un membro in un'espressione di istanza, tale espressione di istanza determina l'oggetto di destinazione del delegato.If the selected method M is an extension method which is denoted by means of a member access on an instance expression, that instance expression determines the target object of the delegate.
  • Il risultato della conversione è un valore di tipo D, ovvero un delegato appena creato che fa riferimento al metodo selezionato e all'oggetto di destinazione.The result of the conversion is a value of type D, namely a newly created delegate that refers to the selected method and target object.
  • Si noti che questo processo può causare la creazione di un delegato a un metodo di estensione, se l'algoritmo delle chiamate al metodo non riesce a trovare un metodo di istanza ma ha esito positivo nell'elaborazione della chiamata di E(A) come chiamata a un metodo di estensione (chiamate al metodo diestensione).Note that this process can lead to the creation of a delegate to an extension method, if the algorithm of Method invocations fails to find an instance method but succeeds in processing the invocation of E(A) as an extension method invocation (Extension method invocations). Un delegato creato in questo modo acquisisce il metodo di estensione e il primo argomento.A delegate thus created captures the extension method as well as its first argument.

Nell'esempio seguente vengono illustrate le conversioni dei gruppi di metodi:The following example demonstrates method group conversions:

delegate string D1(object o);

delegate object D2(string s);

delegate object D3();

delegate string D4(object o, params object[] a);

delegate string D5(int i);

class Test
{
    static string F(object o) {...}

    static void G() {
        D1 d1 = F;            // Ok
        D2 d2 = F;            // Ok
        D3 d3 = F;            // Error -- not applicable
        D4 d4 = F;            // Error -- not applicable in normal form
        D5 d5 = F;            // Error -- applicable but not compatible

    }
}

L'assegnazione a d1 converte in modo implicito il gruppo di metodi F in un valore di tipo D1.The assignment to d1 implicitly converts the method group F to a value of type D1.

L'assegnazione a d2 Mostra come è possibile creare un delegato per un metodo con tipi di parametro meno derivati (controvariante) e un tipo restituito più derivato (covariante).The assignment to d2 shows how it is possible to create a delegate to a method that has less derived (contravariant) parameter types and a more derived (covariant) return type.

L'assegnazione a d3 Mostra in che modo non esiste alcuna conversione se il metodo non è applicabile.The assignment to d3 shows how no conversion exists if the method is not applicable.

L'assegnazione a d4 Mostra come il metodo deve essere applicabile nel formato normale.The assignment to d4 shows how the method must be applicable in its normal form.

L'assegnazione a d5 Mostra come il parametro e i tipi restituiti del delegato e del metodo possono differire solo per i tipi di riferimento.The assignment to d5 shows how parameter and return types of the delegate and method are allowed to differ only for reference types.

Come per tutte le altre conversioni implicite ed esplicite, l'operatore cast può essere utilizzato per eseguire in modo esplicito la conversione di un gruppo di metodi.As with all other implicit and explicit conversions, the cast operator can be used to explicitly perform a method group conversion. Quindi, l'esempioThus, the example

object obj = new EventHandler(myDialog.OkClick);

in alternativa, è possibile scriverecould instead be written

object obj = (EventHandler)myDialog.OkClick;

I gruppi di metodi possono influenzare la risoluzione dell'overload e partecipare all'inferenza del tipo.Method groups may influence overload resolution, and participate in type inference. Per ulteriori informazioni, vedere membri di funzione .See Function members for further details.

La valutazione in fase di esecuzione della conversione di un gruppo di metodi procede come segue:The run-time evaluation of a method group conversion proceeds as follows:

  • Se il metodo selezionato in fase di compilazione è un metodo di istanza o è un metodo di estensione a cui si accede come metodo di istanza, l'oggetto di destinazione del delegato è determinato dall'espressione dell'istanza associata a E:If the method selected at compile-time is an instance method, or it is an extension method which is accessed as an instance method, the target object of the delegate is determined from the instance expression associated with E:
    • L'espressione dell'istanza viene valutata.The instance expression is evaluated. Se questa valutazione causa un'eccezione, non vengono eseguiti altri passaggi.If this evaluation causes an exception, no further steps are executed.
    • Se l'espressione dell'istanza è di un reference_type, il valore calcolato dall'espressione di istanza diventa l'oggetto di destinazione.If the instance expression is of a reference_type, the value computed by the instance expression becomes the target object. Se il metodo selezionato è un metodo di istanza e l'oggetto di destinazione è null, viene generata un'System.NullReferenceException e non vengono eseguiti altri passaggi.If the selected method is an instance method and the target object is null, a System.NullReferenceException is thrown and no further steps are executed.
    • Se l'espressione dell'istanza è di un value_type, viene eseguita un'operazione di conversione boxing (conversioni boxing) per convertire il valore in un oggetto e questo oggetto diventa l'oggetto di destinazione.If the instance expression is of a value_type, a boxing operation (Boxing conversions) is performed to convert the value to an object, and this object becomes the target object.
  • In caso contrario, il metodo selezionato fa parte di una chiamata a un metodo statico e l'oggetto di destinazione del delegato viene null.Otherwise the selected method is part of a static method call, and the target object of the delegate is null.
  • Viene allocata una nuova istanza del tipo delegato D.A new instance of the delegate type D is allocated. Se la memoria disponibile non è sufficiente per allocare la nuova istanza, viene generata un'System.OutOfMemoryException e non vengono eseguiti altri passaggi.If there is not enough memory available to allocate the new instance, a System.OutOfMemoryException is thrown and no further steps are executed.
  • La nuova istanza del delegato viene inizializzata con un riferimento al metodo determinato in fase di compilazione e un riferimento all'oggetto di destinazione calcolato sopra.The new delegate instance is initialized with a reference to the method that was determined at compile-time and a reference to the target object computed above.