KonwersjeConversions

*Konwersja _ umożliwia przetraktowanie wyrażenia jako elementu określonego typu.A *conversion _ enables an expression to be treated as being of a particular type. Konwersja może spowodować, że wyrażenie danego typu ma być traktowane jako mające inny typ lub może spowodować wyrażenie bez typu, aby uzyskać typ.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. Konwersje mogą być niejawne lub _ jawne * i określają, czy wymagane jest jawne rzutowanie.Conversions can be implicit or _*explicit**, and this determines whether an explicit cast is required. Na przykład konwersja z typu int na typ long jest niejawna, dlatego wyrażenia typu int mogą być niejawnie traktowane jako typ 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. Odwrotna konwersja z typu long do typu int jest jawna i dlatego wymagane jest jawne rzutowanie.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

Niektóre konwersje są definiowane przez język.Some conversions are defined by the language. Programy mogą także definiować własne konwersje (konwersje zdefiniowane przez użytkownika).Programs may also define their own conversions (User-defined conversions).

Konwersje niejawneImplicit conversions

Następujące konwersje są klasyfikowane jako konwersje niejawne:The following conversions are classified as implicit conversions:

  • Konwersje tożsamościIdentity conversions
  • Niejawne konwersje liczboweImplicit numeric conversions
  • Niejawne konwersje wyliczeniaImplicit enumeration conversions
  • Niejawne konwersje ciągu interpolowanegoImplicit interpolated string conversions
  • Niejawne konwersje dopuszczające wartość nullImplicit nullable conversions
  • Konwersje literałów nullNull literal conversions
  • Niejawne konwersje odwołańImplicit reference conversions
  • Konwersje z opakowaniaBoxing conversions
  • Niejawne konwersje dynamiczneImplicit dynamic conversions
  • Niejawne konwersje wyrażeń stałychImplicit constant expression conversions
  • Konwersje niejawne zdefiniowane przez użytkownikaUser-defined implicit conversions
  • Konwersje funkcji anonimowychAnonymous function conversions
  • Konwersje grup metodMethod group conversions

Konwersje niejawne mogą odbywać się w różnych sytuacjach, w tym wywołaniach elementów członkowskich funkcji (Sprawdzanie czasu kompilacji dynamicznego rozpoznawania przeciążenia), wyrażenia rzutowania (wyrażenia rzutowania) i przypisania (Operatory przypisywania).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).

Wstępnie zdefiniowane konwersje niejawne zawsze kończą się powodzeniem i nigdy nie powodują zgłaszania wyjątków.The pre-defined implicit conversions always succeed and never cause exceptions to be thrown. Odpowiednio zaprojektowane zdefiniowane przez użytkownika Konwersje niejawne powinny również mieć te cechy.Properly designed user-defined implicit conversions should exhibit these characteristics as well.

Na potrzeby konwersji typy object i dynamic są uważane za równoważne.For the purposes of conversion, the types object and dynamic are considered equivalent.

Jednak konwersje dynamiczne (niejawne konwersje dynamiczne i jawne konwersje dynamiczne) mają zastosowanie tylko do wyrażeń typu dynamic (Typ dynamiczny).However, dynamic conversions (Implicit dynamic conversions and Explicit dynamic conversions) apply only to expressions of type dynamic (The dynamic type).

Konwersja tożsamościIdentity conversion

Konwersja tożsamości jest konwertowana z dowolnego typu na ten sam typ.An identity conversion converts from any type to the same type. Ta konwersja istnieje w taki sposób, aby jednostka, która już ma wymagany typ, mogła zostać poddana konwersji na ten typ.This conversion exists such that an entity that already has a required type can be said to be convertible to that type.

  • Ponieważ object i dynamic są uważane za równoważne, istnieje konwersja tożsamości między object i i dynamic między tworzonymi typami, które są takie same podczas zamieniania wszystkich wystąpień dynamic z 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.

Niejawne konwersje liczboweImplicit numeric conversions

Niejawne konwersje liczbowe są następujące:The implicit numeric conversions are:

  • Z sbyte do short , int ,,, long float double lub decimal .From sbyte to short, int, long, float, double, or decimal.
  • Z byte do,,,,,,,, short ushort int uint long ulong float double lub decimal .From byte to short, ushort, int, uint, long, ulong, float, double, or decimal.
  • Od short do int , long , float , double lub decimal .From short to int, long, float, double, or decimal.
  • Z ushort do int ,,,,, uint long ulong float double lub decimal .From ushort to int, uint, long, ulong, float, double, or decimal.
  • Z int do long , float , double , lub decimal .From int to long, float, double, or decimal.
  • Od uint do long , ulong , float , double lub decimal .From uint to long, ulong, float, double, or decimal.
  • Z long do float , double lub decimal .From long to float, double, or decimal.
  • Z ulong do float , double lub decimal .From ulong to float, double, or decimal.
  • Z char do ushort ,,,,, int uint long ulong float , double lub decimal .From char to ushort, int, uint, long, ulong, float, double, or decimal.
  • Z float do double .From float to double.

Konwersje z int , uint , long , lub ulong do float i z oraz do i z long lub ulong do double mogą spowodować utratę precyzji, ale nigdy nie spowodują utraty wielkości.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. Inne niejawne konwersje numeryczne nigdy nie tracą żadnych informacji.The other implicit numeric conversions never lose any information.

Brak niejawnych konwersji do char typu, dlatego wartości innych typów całkowitych nie są automatycznie konwertowane na char Typ.There are no implicit conversions to the char type, so values of the other integral types do not automatically convert to the char type.

Niejawne konwersje wyliczeniaImplicit enumeration conversions

Niejawna konwersja Wyliczenie zezwala na 0 konwersję decimal_integer_literal na dowolną enum_type i dla każdego nullable_type , którego typ podstawowy jest 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. W tym drugim przypadku konwersja jest oceniana przez przekonwertowanie na bazowe enum_type i Zawijanie wyniku (Typy dopuszczające wartość null).In the latter case the conversion is evaluated by converting to the underlying enum_type and wrapping the result (Nullable types).

Niejawne konwersje ciągu interpolowanegoImplicit interpolated string conversions

Niejawna konwersja ciągu interpolowanego zezwala na konwersję interpolated_string_expression (ciągów interpolowanych) na System.IFormattable lub System.FormattableString (które implementują 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).

Gdy ta konwersja jest stosowana, wartość ciągu nie jest złożona z ciągu interpolowanego.When this conversion is applied a string value is not composed from the interpolated string. W zamian wystąpienie System.FormattableString jest tworzone, jak dokładniej opisane w ciągach interpolowanych.Instead an instance of System.FormattableString is created, as further described in Interpolated strings.

Niejawne konwersje dopuszczające wartość nullImplicit nullable conversions

Wstępnie zdefiniowane konwersje niejawne, które działają na typach wartości, które nie dopuszczają wartości null, mogą również być używane z dopuszczaniem wartości null dla tych typów.Predefined implicit conversions that operate on non-nullable value types can also be used with nullable forms of those types. Dla wszystkich wstępnie zdefiniowanych niejawnych tożsamości i konwersji liczbowych, które są konwertowane z typu wartości niedopuszczające wartości null S do typu wartości niedopuszczających wartości null T , istnieją następujące niejawne konwersje dopuszczające wartość null: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:

  • Niejawna konwersja z S? na T? .An implicit conversion from S? to T?.
  • Niejawna konwersja z S na T? .An implicit conversion from S to T?.

Obliczanie niejawnej konwersji dopuszczanej do wartości null na podstawie podstawowej konwersji z S programu do T postępuje w następujący sposób:Evaluation of an implicit nullable conversion based on an underlying conversion from S to T proceeds as follows:

  • Jeśli konwersja dopuszcza wartość null z S? do T? :If the nullable conversion is from S? to T?:

    • Jeśli wartość źródłowa jest równa null ( HasValue Właściwość ma wartość false), wynik jest wartością null typu T? .If the source value is null (HasValue property is false), the result is the null value of type T?.
    • W przeciwnym razie konwersja jest oceniana jako odpakowanie od S? do S , a następnie bazowa konwersja z S do T , po którym następuje Zawijanie (Typy dopuszczające wartość null) z T do 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?.
  • Jeśli konwersja z dopuszczaniem wartości null jest z S do T? , konwersja jest szacowana jako konwersja bazowa S z T elementu, po którym następuje Zawijanie z T do 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?.

Konwersje literałów nullNull literal conversions

Niejawna konwersja istnieje z null literału do dowolnego typu dopuszczającego wartość null.An implicit conversion exists from the null literal to any nullable type. Ta konwersja generuje wartość null (Typy Nullable) danego typu dopuszczającego wartości null.This conversion produces the null value (Nullable types) of the given nullable type.

Niejawne konwersje odwołańImplicit reference conversions

Konwersje niejawnych odwołań są następujące:The implicit reference conversions are:

  • Z dowolnego reference_type do object i dynamic .From any reference_type to object and dynamic.
  • Z dowolnego S class_type class_type T dostarczonego przez S T .From any class_type S to any class_type T, provided S is derived from T.
  • Na podstawie dowolnych class_type S do dowolnych INTERFACE_TYPE T S T .From any class_type S to any interface_type T, provided S implements T.
  • Z dowolnego S INTERFACE_TYPE INTERFACE_TYPE T dostarczonego przez S T .From any interface_type S to any interface_type T, provided S is derived from T.
  • Z array_type S z typem elementu SE do array_type T z typem elementu TE , pod warunkiem spełnione są wszystkie z następujących warunków: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 i T różnią się tylko w typie elementu.S and T differ only in element type. Innymi słowy S i ma taką T samą liczbę wymiarów.In other words, S and T have the same number of dimensions.
    • Oba SE i TEreference_type s.Both SE and TE are reference_type s.
    • Niejawna konwersja odwołania istnieje z SE do TE .An implicit reference conversion exists from SE to TE.
  • Z dowolnego array_type do System.Array i interfejsów, które implementuje.From any array_type to System.Array and the interfaces it implements.
  • Z jednowymiarowego typu tablicy S[] do System.Collections.Generic.IList<T> i jego interfejsów podstawowych, pod warunkiem, że istnieje niejawna tożsamość lub konwersja odwołań z S do 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.
  • Z dowolnego delegate_type do System.Delegate i interfejsów, które implementuje.From any delegate_type to System.Delegate and the interfaces it implements.
  • Z literału null do dowolnego reference_type.From the null literal to any reference_type.
  • Z dowolnego reference_type do reference_type , T Jeśli ma niejawną tożsamość lub konwersję odwołania do reference_type T0 i T0 ma konwersję tożsamości na 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.
  • Z dowolnego reference_type do interfejsu lub typu delegata, T Jeśli ma niejawną tożsamość lub konwersję referencyjną do interfejsu lub typu delegata T0 i jest konwersją T0 wariancji (Konwersja wariancji) na 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.
  • Niejawne konwersje obejmujące parametry typu, które są znane jako typy odwołań.Implicit conversions involving type parameters that are known to be reference types. Zobacz niejawne konwersje dotyczące parametrów typu , aby uzyskać więcej informacji na temat niejawnych konwersji obejmujących parametry typu.See Implicit conversions involving type parameters for more details on implicit conversions involving type parameters.

Konwersje niejawnych odwołań są tymi konwersjami między reference_type s, które mogą być sprawdzone, aby zawsze kończyły się powodzeniem, dlatego nie wymagają kontroli w czasie wykonywania.The implicit reference conversions are those conversions between reference_type s that can be proven to always succeed, and therefore require no checks at run-time.

Konwersje odwołań, niejawne lub jawne, nigdy nie zmieniają tożsamości referencyjnej konwertowanego obiektu.Reference conversions, implicit or explicit, never change the referential identity of the object being converted. Innymi słowy, podczas gdy konwersja odwołania może zmienić typ odwołania, nigdy nie zmienia typu lub wartości obiektu, do którego odwołuje się.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.

Konwersje z opakowaniaBoxing conversions

Konwersja z opakowania zezwala na niejawne przekonwertowanie value_type na typ referencyjny.A boxing conversion permits a value_type to be implicitly converted to a reference type. Konwersja z opakowania istnieje z dowolnego non_nullable_value_type do object i do dynamic System.ValueType wszystkich INTERFACE_TYPE implementowanych przez 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. Ponadto enum_type można przekonwertować na typ System.Enum .Furthermore an enum_type can be converted to the type System.Enum.

Konwersja z opakowania istnieje z nullable_type do typu referencyjnego, jeśli i tylko wtedy, gdy istnieje konwersja z bazowego non_nullable_value_type do typu odwołania.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.

Typ wartości ma zapakowywanie konwersji do typu interfejsu I , jeśli ma ona konwersję na typ interfejsu I0 i I0 ma konwersję tożsamości na 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.

Typ wartości ma konwersję z opakowaniem do typu interfejsu, I Jeśli ma ona konwersję na typ interfejsu lub delegata I0 i I0 jest zmienności wariancji (Konwersja wariancji) na 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.

Opakowanie wartości non_nullable_value_type obejmuje przydzielenie wystąpienia obiektu i skopiowanie wartości value_type do tego wystąpienia.Boxing a value of a non_nullable_value_type consists of allocating an object instance and copying the value_type value into that instance. Struktura może być opakowana do typu System.ValueType , ponieważ jest klasą bazową dla wszystkich struktur (dziedziczenie).A struct can be boxed to the type System.ValueType, since that is a base class for all structs (Inheritance).

Wypakowywanie wartości nullable_type jest następująca:Boxing a value of a nullable_type proceeds as follows:

  • Jeśli wartość źródłowa jest równa null ( HasValue Właściwość ma wartość false), wynik jest odwołaniem null typu docelowego.If the source value is null (HasValue property is false), the result is a null reference of the target type.
  • W przeciwnym razie wynik jest odwołaniem do opakowanego T tekstu przez odpakowywanie i opakowanie wartości źródłowej.Otherwise, the result is a reference to a boxed T produced by unwrapping and boxing the source value.

Konwersje napakowywania są opisane w dalszej konwersji opakowania.Boxing conversions are described further in Boxing conversions.

Niejawne konwersje dynamiczneImplicit dynamic conversions

Niejawna konwersja dynamiczna istnieje z wyrażenia typu dynamic do dowolnego typu T .An implicit dynamic conversion exists from an expression of type dynamic to any type T. Konwersja jest powiązana dynamicznie (powiązanie dynamiczne), co oznacza, że niejawna konwersja zostanie poszukiwana w czasie wykonywania z typu wyrażenia do 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. Jeśli konwersja nie zostanie znaleziona, zostanie zgłoszony wyjątek czasu wykonywania.If no conversion is found, a run-time exception is thrown.

Należy zauważyć, że ta niejawna konwersja pozornie narusza wskazówkę na początku konwersji niejawnych , których niejawna konwersja nigdy nie powinna spowodować wyjątku.Note that this implicit conversion seemingly violates the advice in the beginning of Implicit conversions that an implicit conversion should never cause an exception. Nie jest to jednak sama konwersja, ale Wyszukiwanie konwersji, która powoduje wyjątek.However it is not the conversion itself, but the finding of the conversion that causes the exception. Ryzyko wyjątków w czasie wykonywania jest związane z użyciem powiązania dynamicznego.The risk of run-time exceptions is inherent in the use of dynamic binding. Jeśli dynamiczne powiązanie konwersji nie jest wymagane, można najpierw przekonwertować wyrażenie na object , a następnie na żądany typ.If dynamic binding of the conversion is not desired, the expression can be first converted to object, and then to the desired type.

Poniższy przykład ilustruje niejawne konwersje dynamiczne: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

Przypisania do s2 i i oba wykorzystują niejawne konwersje dynamiczne, w przypadku których powiązanie operacji jest wstrzymane do czasu wykonania.The assignments to s2 and i both employ implicit dynamic conversions, where the binding of the operations is suspended until run-time. W czasie wykonywania niejawne konwersje są odszukiwane od typu czasu wykonywania d -- string --do typu docelowego.At run-time, implicit conversions are sought from the run-time type of d -- string -- to the target type. Konwersja zostanie znaleziona, string ale nie do int .A conversion is found to string but not to int.

Niejawne konwersje wyrażeń stałychImplicit constant expression conversions

Niejawna konwersja wyrażeń stałych umożliwia wykonywanie następujących konwersji:An implicit constant expression conversion permits the following conversions:

  • Constant_expression (wyrażenia stałe) typu int można przekonwertować na typ sbyte ,,,, byte short ushort uint , lub ulong , pod warunkiem, że wartość constant_expression znajduje się w zakresie typu docelowego.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.
  • Constant_expression typu long można przekonwertować na typ ulong , pod warunkiem, że wartość constant_expression nie jest ujemna.A constant_expression of type long can be converted to type ulong, provided the value of the constant_expression is not negative.

Niejawne konwersje obejmujące parametry typuImplicit conversions involving type parameters

Następujące konwersje niejawne istnieją dla danego parametru typu T :The following implicit conversions exist for a given type parameter T:

  • Od T do jej obowiązującej klasy podstawowej C , od T do dowolnej klasy bazowej C , i od T do dowolnego interfejsu zaimplementowanego przez 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. W czasie wykonywania, jeśli T jest typem wartości, konwersja jest wykonywana jako konwersja z opakowania.At run-time, if T is a value type, the conversion is executed as a boxing conversion. W przeciwnym razie konwersja jest wykonywana jako niejawna konwersja odwołania lub konwersja tożsamości.Otherwise, the conversion is executed as an implicit reference conversion or identity conversion.
  • Z T do typu interfejsu I w T skutecznym interfejsie i od T do dowolnego interfejsu podstawowego programu I .From T to an interface type I in T's effective interface set and from T to any base interface of I. W czasie wykonywania, jeśli T jest typem wartości, konwersja jest wykonywana jako konwersja z opakowania.At run-time, if T is a value type, the conversion is executed as a boxing conversion. W przeciwnym razie konwersja jest wykonywana jako niejawna konwersja odwołania lub konwersja tożsamości.Otherwise, the conversion is executed as an implicit reference conversion or identity conversion.
  • Wartość z T do parametru typu jest U T zależna od U (ograniczenia parametru typu).From T to a type parameter U, provided T depends on U (Type parameter constraints). W czasie wykonywania, jeśli U jest typem wartości, T i jest U koniecznie tego samego typu, a konwersja nie jest przeprowadzana.At run-time, if U is a value type, then T and U are necessarily the same type and no conversion is performed. W przeciwnym razie, jeśli T jest typem wartości, konwersja jest wykonywana jako konwersja z opakowania.Otherwise, if T is a value type, the conversion is executed as a boxing conversion. W przeciwnym razie konwersja jest wykonywana jako niejawna konwersja odwołania lub konwersja tożsamości.Otherwise, the conversion is executed as an implicit reference conversion or identity conversion.
  • Z poziomu literału null do T , dostarczony T jest znany jako typ referencyjny.From the null literal to T, provided T is known to be a reference type.
  • Od T do typu referencyjnego, I Jeśli ma niejawną konwersję na typ referencyjny S0 i S0 ma konwersję tożsamości na 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. W czasie wykonywania konwersja jest wykonywana w taki sam sposób jak w przypadku konwersji do S0 .At run-time the conversion is executed the same way as the conversion to S0.
  • Od T do typu interfejsu, I Jeśli ma niejawną konwersję na typ interfejsu lub delegata I0 i jest konwersją I0 wariancji na I (Konwersja wariancji).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). W czasie wykonywania, jeśli T jest typem wartości, konwersja jest wykonywana jako konwersja z opakowania.At run-time, if T is a value type, the conversion is executed as a boxing conversion. W przeciwnym razie konwersja jest wykonywana jako niejawna konwersja odwołania lub konwersja tożsamości.Otherwise, the conversion is executed as an implicit reference conversion or identity conversion.

Jeśli T jest znany jako typ referencyjny (ograniczenia parametru typu), powyższe konwersje są klasyfikowane jako niejawne konwersje odwołań (niejawne konwersje odwołań).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). Jeśli T nie jest to typ referencyjny, powyższe konwersje są klasyfikowane jako konwersje z opakowaniem (konwersje z opakowania).If T is not known to be a reference type, the conversions above are classified as boxing conversions (Boxing conversions).

Konwersje niejawne zdefiniowane przez użytkownikaUser-defined implicit conversions

Niejawna konwersja zdefiniowana przez użytkownika składa się z opcjonalnej standardowej konwersji niejawnej, a następnie wykonania operatora niejawnej konwersji zdefiniowanej przez użytkownika, a następnie innej opcjonalnej standardowej konwersji niejawnej.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. Dokładne reguły oceniania niejawnych konwersji zdefiniowanych przez użytkownika są opisane w temacie Przetwarzanie konwersji niejawnych zdefiniowanych przez użytkownika.The exact rules for evaluating user-defined implicit conversions are described in Processing of user-defined implicit conversions.

Konwersje funkcji anonimowych i konwersje grup metodAnonymous function conversions and method group conversions

Funkcje anonimowe i grupy metod nie mają typów w i samych siebie, ale mogą być niejawnie konwertowane na typy delegatów lub typy drzewa wyrażeń.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. Konwersje funkcji anonimowych są opisane bardziej szczegółowo w przypadku konwersji funkcji anonimowych i konwersji grup metod w przypadku konwersji grup metod.Anonymous function conversions are described in more detail in Anonymous function conversions and method group conversions in Method group conversions.

Konwersje jawneExplicit conversions

Następujące konwersje są klasyfikowane jako Konwersje jawne:The following conversions are classified as explicit conversions:

  • Wszystkie konwersje niejawne.All implicit conversions.
  • Jawne konwersje numeryczne.Explicit numeric conversions.
  • Jawne konwersje Wyliczenie.Explicit enumeration conversions.
  • Jawne konwersje dopuszczające wartość null.Explicit nullable conversions.
  • Jawne konwersje odwołań.Explicit reference conversions.
  • Jawne konwersje interfejsów.Explicit interface conversions.
  • Konwersje rozpakowywanie.Unboxing conversions.
  • Jawne konwersje dynamiczneExplicit dynamic conversions
  • Jawne konwersje zdefiniowane przez użytkownika.User-defined explicit conversions.

Jawne konwersje mogą wystąpić w wyrażeniach rzutowania (wyrażenia rzutowania).Explicit conversions can occur in cast expressions (Cast expressions).

Zestaw jawnych konwersji zawiera wszystkie konwersje niejawne.The set of explicit conversions includes all implicit conversions. Oznacza to, że dozwolone są nadmiarowe wyrażenia rzutowania.This means that redundant cast expressions are allowed.

Jawne konwersje, które nie są konwersjemi niejawnymi to konwersje, które nie mogą być sprawdzane, aby zawsze kończyły się powodzeniem, konwersje, które są znane do utraty informacji, a także konwersje między domenami typów wystarczająco różne do określenia jawnej notacji.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.

Jawne konwersje numeryczneExplicit numeric conversions

Jawne konwersje numeryczne to konwersje z numeric_type do innej numeric_type , dla których niejawna konwersja liczbowa (niejawne konwersje liczbowe) jeszcze nie istnieje: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:

  • Od sbyte do byte , ushort , uint , ulong lub char .From sbyte to byte, ushort, uint, ulong, or char.
  • Z byte do sbyte i char .From byte to sbyte and char.
  • Z short do sbyte , byte ,,, ushort uint ulong lub char .From short to sbyte, byte, ushort, uint, ulong, or char.
  • Z ushort do sbyte , byte , short , lub char .From ushort to sbyte, byte, short, or char.
  • Z int do sbyte ,,,,, byte short ushort uint ulong lub char .From int to sbyte, byte, short, ushort, uint, ulong, or char.
  • Z uint do sbyte , byte ,,, short ushort int lub char .From uint to sbyte, byte, short, ushort, int, or char.
  • Z long do sbyte ,,,,, byte short ushort int uint , ulong lub char .From long to sbyte, byte, short, ushort, int, uint, ulong, or char.
  • Z ulong do sbyte ,,,,, byte short ushort int uint , long lub char .From ulong to sbyte, byte, short, ushort, int, uint, long, or char.
  • Z char do sbyte , byte lub short .From char to sbyte, byte, or short.
  • Od float do,,,,,,,, sbyte byte short ushort int uint long ulong char lub decimal .From float to sbyte, byte, short, ushort, int, uint, long, ulong, char, or decimal.
  • Z do,,,,,,,,, double sbyte byte short ushort int uint long ulong char float , lub decimal .From double to sbyte, byte, short, ushort, int, uint, long, ulong, char, float, or decimal.
  • Z do,,,,,,,,, decimal sbyte byte short ushort int uint long ulong char float , lub double .From decimal to sbyte, byte, short, ushort, int, uint, long, ulong, char, float, or double.

Ponieważ jawne konwersje obejmują wszystkie niejawnych i jawnych konwersji liczbowych, zawsze możliwe jest przekonwertowanie z dowolnego numeric_type na inne numeric_type przy użyciu wyrażenia CAST (wyrażenia rzutowania).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).

Jawne konwersje numeryczne mogą spowodować utratę informacji lub spowodować, że wyjątki mają być zgłaszane.The explicit numeric conversions possibly lose information or possibly cause exceptions to be thrown. Jawna konwersja liczbowa jest przetwarzana w następujący sposób:An explicit numeric conversion is processed as follows:

  • Dla konwersji z typu całkowitego na inny typ całkowity, przetwarzanie zależy od kontekstu sprawdzania przepełnienia (Operatory sprawdzone i niesprawdzane), w którym odbywa się konwersja: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:
    • W checked kontekście konwersja powiedzie się, jeśli wartość operandu źródłowego należy do zakresu typu docelowego, ale zgłasza System.OverflowException wartość, jeśli argument operacji źródła znajduje się poza zakresem typu docelowego.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.
    • W unchecked kontekście konwersja zawsze kończy się powodzeniem i przechodzi w następujący sposób.In an unchecked context, the conversion always succeeds, and proceeds as follows.
      • Jeśli typ źródła jest większy niż typ docelowy, wartość źródłowa zostanie obcięta przez odrzucenie jej najbardziej znaczących bitów.If the source type is larger than the destination type, then the source value is truncated by discarding its "extra" most significant bits. Następnie wynik jest traktowany jako wartość typu docelowego.The result is then treated as a value of the destination type.
      • Jeśli typ źródła jest mniejszy niż typ docelowy, wartość źródłowa jest podwyższana lub równa zero, tak że jest to ten sam rozmiar, co typ docelowy.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. Jeśli typ źródła jest podpisany, jest używane rozszerzenie-znak. Jeśli typ źródła jest niepodpisany, jest używane rozszerzenie o wartości zero.Sign-extension is used if the source type is signed; zero-extension is used if the source type is unsigned. Następnie wynik jest traktowany jako wartość typu docelowego.The result is then treated as a value of the destination type.
      • Jeśli typ źródła ma taki sam rozmiar jak typ docelowy, wartość źródłowa jest traktowana jako wartość typu docelowego.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.
  • Dla konwersji z decimal do typu całkowitego wartość źródłowa jest zaokrąglana do zera do najbliższej wartości całkowitej, a ta wartość całkowita jest wynikiem konwersji.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. Jeśli uzyskana wartość całkowita jest poza zakresem typu docelowego, System.OverflowException jest zgłaszany.If the resulting integral value is outside the range of the destination type, a System.OverflowException is thrown.
  • Dla konwersji z float lub double do typu całkowitego, przetwarzanie zależy od kontekstu sprawdzania przepełnienia (Operatory sprawdzone i niesprawdzone), w którym odbywa się konwersja: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:
    • W checked kontekście konwersja wykonuje następujące czynności:In a checked context, the conversion proceeds as follows:
      • Jeśli wartość operandu jest NaN lub nieskończona, System.OverflowException jest zgłaszany.If the value of the operand is NaN or infinite, a System.OverflowException is thrown.
      • W przeciwnym razie argument źródłowy jest zaokrąglany do zera do najbliższej wartości całkowitej.Otherwise, the source operand is rounded towards zero to the nearest integral value. Jeśli ta wartość całkowita znajduje się w zakresie typu docelowego, ta wartość jest wynikiem konwersji.If this integral value is within the range of the destination type then this value is the result of the conversion.
      • W przeciwnym razie System.OverflowException jest zgłaszany.Otherwise, a System.OverflowException is thrown.
    • W unchecked kontekście konwersja zawsze kończy się powodzeniem i przechodzi w następujący sposób.In an unchecked context, the conversion always succeeds, and proceeds as follows.
      • Jeśli wartość operandu jest NaN lub nieskończona, wynik konwersji jest nieokreśloną wartością typu docelowego.If the value of the operand is NaN or infinite, the result of the conversion is an unspecified value of the destination type.
      • W przeciwnym razie argument źródłowy jest zaokrąglany do zera do najbliższej wartości całkowitej.Otherwise, the source operand is rounded towards zero to the nearest integral value. Jeśli ta wartość całkowita znajduje się w zakresie typu docelowego, ta wartość jest wynikiem konwersji.If this integral value is within the range of the destination type then this value is the result of the conversion.
      • W przeciwnym razie wynik konwersji jest nieokreśloną wartością typu docelowego.Otherwise, the result of the conversion is an unspecified value of the destination type.
  • Dla konwersji z double do float , double wartość jest zaokrąglana do najbliższej float wartości.For a conversion from double to float, the double value is rounded to the nearest float value. Jeśli double wartość jest zbyt mała do reprezentowania jako float , wynik przyjmie wartość dodatnią zero lub ujemną zero.If the double value is too small to represent as a float, the result becomes positive zero or negative zero. Jeśli double wartość jest zbyt duża, aby reprezentować ją jako float , wynik będzie dodatnią nieskończoność lub ujemną nieskończoność.If the double value is too large to represent as a float, the result becomes positive infinity or negative infinity. Jeśli double wartość jest NaN, wynik jest również NaN.If the double value is NaN, the result is also NaN.
  • Dla konwersji z float lub double do decimal , wartość źródłowa jest konwertowana na decimal reprezentację i zaokrąglana do najbliższej liczby po 28 miejscach dziesiętnych, jeśli jest to wymagane (Typ dziesiętny).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). Jeśli wartość źródłowa jest zbyt mała do reprezentowania jako decimal , wynik zmieni się na zero.If the source value is too small to represent as a decimal, the result becomes zero. Jeśli wartością źródłową jest NaN, nieskończoność lub zbyt duża do reprezentowania jako decimal , System.OverflowException jest generowany.If the source value is NaN, infinity, or too large to represent as a decimal, a System.OverflowException is thrown.
  • Dla konwersji z decimal do float lub double , decimal wartość jest zaokrąglana do najbliższej double lub float wartości.For a conversion from decimal to float or double, the decimal value is rounded to the nearest double or float value. Ta konwersja może spowodować utratę precyzji, ale nigdy nie powoduje zgłoszenia wyjątku.While this conversion may lose precision, it never causes an exception to be thrown.

Jawne konwersje wyliczeniaExplicit enumeration conversions

Jawne konwersje Wyliczenie są następujące:The explicit enumeration conversions are:

  • Od,,,,,,,,,, sbyte byte short ushort int uint long ulong char float double lub decimal do dowolnego enum_type.From sbyte, byte, short, ushort, int, uint, long, ulong, char, float, double, or decimal to any enum_type.
  • Z dowolnego enum_type do,,,,,,,,,, sbyte byte short ushort int uint long ulong char float double lub decimal .From any enum_type to sbyte, byte, short, ushort, int, uint, long, ulong, char, float, double, or decimal.
  • Z dowolnego enum_type do dowolnego innego enum_type.From any enum_type to any other enum_type.

Jawna konwersja wyliczenia między dwoma typami jest przetwarzana przez traktowanie wszelkich uczestniczących enum_type jako typ podstawowy tego enum_type, a następnie wykonywanie niejawnej lub jawnej konwersji liczbowej między wynikiem.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. Na przykład w przypadku enum_type E z i typem podstawowym klasy int Konwersja z E do na byte jest przetwarzana jako jawna konwersja liczbowa (jawne konwersje liczbowe) z int do byte , a konwersja z byte do na E jest przetwarzana jako niejawna konwersja liczbowa (niejawne konwersje liczbowe) z byte do 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.

Jawne konwersje dopuszczające wartość nullExplicit nullable conversions

Jawne konwersje wartości null zezwalają na wstępnie zdefiniowane Konwersje jawne, które działają dla typów wartościowych niedopuszczających wartości null, aby były również używane z dopuszczaniem wartości null dla tych typów.Explicit nullable conversions permit predefined explicit conversions that operate on non-nullable value types to also be used with nullable forms of those types. Dla każdej z wstępnie zdefiniowanych konwersji jawnych, które konwertują z typu wartości niedopuszczających wartości null S T (konwersja tożsamości, niejawne konwersje liczbowe, niejawne konwersje wyliczenia, jawne konwersje liczbowei jawne konwersje wyliczenia), istnieją następujące konwersje dopuszczające wartość null: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:

  • Jawna konwersja z S? do T? .An explicit conversion from S? to T?.
  • Jawna konwersja z S do T? .An explicit conversion from S to T?.
  • Jawna konwersja z S? do T .An explicit conversion from S? to T.

Obliczanie konwersji dopuszczającej wartość null na podstawie bazowej konwersji z S programu do T postępuje w następujący sposób:Evaluation of a nullable conversion based on an underlying conversion from S to T proceeds as follows:

  • Jeśli konwersja dopuszcza wartość null z S? do T? :If the nullable conversion is from S? to T?:
    • Jeśli wartość źródłowa jest równa null ( HasValue Właściwość ma wartość false), wynik jest wartością null typu T? .If the source value is null (HasValue property is false), the result is the null value of type T?.
    • W przeciwnym razie konwersja jest oceniana jako odpakowanie od S? do S , a następnie bazowa konwersja z S do T , po którym następuje Zawijanie z T do 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?.
  • Jeśli konwersja z dopuszczaniem wartości null jest z S do T? , konwersja jest szacowana jako konwersja bazowa S z T elementu, po którym następuje Zawijanie z T do 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?.
  • Jeśli konwersja dopuszczający wartość null jest z S? do T , konwersja jest oceniana jako odpakowanie od S? do, S po którym następuje bazowa konwersja z S do 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.

Należy zauważyć, że próba odpakowania wartości null spowoduje zgłoszenie wyjątku, jeśli wartość jest null .Note that an attempt to unwrap a nullable value will throw an exception if the value is null.

Jawne konwersje odwołańExplicit reference conversions

Jawne konwersje odwołań są następujące:The explicit reference conversions are:

  • Od object i dynamic do innych reference_type.From object and dynamic to any other reference_type.
  • Z dowolnego class_typeu S do dowolnego class_type T , dostarczone S jest klasa bazowa T .From any class_type S to any class_type T, provided S is a base class of T.
  • Z dowolnego class_typeu S do dowolnego INTERFACE_TYPE T dostarczony nie S jest zapieczętowany i nie można go S zaimplementować T .From any class_type S to any interface_type T, provided S is not sealed and provided S does not implement T.
  • Z dowolnego interface_typeu S do dowolnego class_type T podane T nie jest zapieczętowane ani dostarczone T S .From any interface_type S to any class_type T, provided T is not sealed or provided T implements S.
  • Z dowolnego interface_typeu S do dowolnego INTERFACE_TYPE T dostarczone S nie są wyprowadzane z T .From any interface_type S to any interface_type T, provided S is not derived from T.
  • Z array_type S z typem elementu SE do array_type T z typem elementu TE , pod warunkiem spełnione są wszystkie z następujących warunków: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 i T różnią się tylko w typie elementu.S and T differ only in element type. Innymi słowy S i ma taką T samą liczbę wymiarów.In other words, S and T have the same number of dimensions.
    • Oba SE i TEreference_type s.Both SE and TE are reference_type s.
    • Jawna konwersja odwołań istnieje z SE do TE .An explicit reference conversion exists from SE to TE.
  • Z System.Array i interfejsów, które implementuje do dowolnego array_type.From System.Array and the interfaces it implements to any array_type.
  • Z jednowymiarowego typu tablicy S[] do System.Collections.Generic.IList<T> i jego interfejsów podstawowych, pod warunkiem, że istnieje jawna konwersja referencyjna z S do 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.
  • Z System.Collections.Generic.IList<S> i jego interfejsów podstawowych do jednowymiarowego typu tablicy T[] , pod warunkiem, że istnieje jawna tożsamość lub konwersja odwołania z S do 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.
  • Z System.Delegate i interfejsów, które implementuje do dowolnego delegate_type.From System.Delegate and the interfaces it implements to any delegate_type.
  • Z typu referencyjnego na typ referencyjny, T Jeśli ma on jawną konwersję odniesienia na typ referencyjny T0 i T0 ma konwersję tożsamości 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.
  • Z typu referencyjnego do interfejsu lub delegata, T Jeśli ma jawną konwersję referencyjną do typu interfejsu lub delegata T0 , a jest to WARIANCJA do konwersji wariancji na T0 T T T0 (Konwersja wariancji).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).
  • Od D<S1...Sn> do D<T1...Tn> gdzie D<X1...Xn> jest ogólny typ delegata, D<S1...Sn> nie jest zgodny z lub identyczny z D<T1...Tn> i dla każdego parametru typu Xi z D następujących: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:
    • Jeśli Xi jest niezmienna, wówczas Si jest taka sama jak Ti .If Xi is invariant, then Si is identical to Ti.
    • Jeśli Xi jest to współwariant, istnieje niejawna lub jawna tożsamość lub konwersja odwołania z Si do Ti .If Xi is covariant, then there is an implicit or explicit identity or reference conversion from Si to Ti.
    • Jeśli Xi jest kontrawariantne, Si i Ti są identyczne lub oba typy odwołań.If Xi is contravariant, then Si and Ti are either identical or both reference types.
  • Jawne konwersje obejmujące parametry typu, które są znane jako typy odwołań.Explicit conversions involving type parameters that are known to be reference types. Aby uzyskać więcej informacji na temat jawnych konwersji obejmujących parametry typu, zobacz jawne konwersje dotyczące parametrów typu.For more details on explicit conversions involving type parameters, see Explicit conversions involving type parameters.

Jawne konwersje referencyjne to konwersje między typami referencyjnymi wymagającymi kontroli w czasie wykonywania, aby upewnić się, że są poprawne.The explicit reference conversions are those conversions between reference-types that require run-time checks to ensure they are correct.

Aby konwersja jawnego odwołania powiodła się w czasie wykonywania, wartość operandu Source musi być null lub rzeczywisty typ obiektu, do którego odwołuje się argument operacji source, musi być typem, który można przekonwertować na typ docelowy przez niejawną konwersję odwołania (niejawne konwersje odwołań) lub konwersję z opakowaniem (konwersje na opakowanie).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). Jeśli jawna konwersja referencyjna nie powiedzie się, System.InvalidCastException zostanie zgłoszony.If an explicit reference conversion fails, a System.InvalidCastException is thrown.

Konwersje odwołań, niejawne lub jawne, nigdy nie zmieniają tożsamości referencyjnej konwertowanego obiektu.Reference conversions, implicit or explicit, never change the referential identity of the object being converted. Innymi słowy, podczas gdy konwersja odwołania może zmienić typ odwołania, nigdy nie zmienia typu lub wartości obiektu, do którego odwołuje się.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.

Odpakowywanie konwersjiUnboxing conversions

Konwersja rozpakowywania umożliwia jawne przekonwertowanie typu odwołania na value_type.An unboxing conversion permits a reference type to be explicitly converted to a value_type. Konwersja rozpakowywania istnieje z typów object dynamic i System.ValueType do dowolnego non_nullable_value_type oraz z dowolnego interface_type do dowolnego non_nullable_value_type implementującego 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. Ponadto typ System.Enum może być rozpakowany do dowolnego enum_type.Furthermore type System.Enum can be unboxed to any enum_type.

Konwersja rozpakowywania istnieje z typu referencyjnego na nullable_type , jeśli istnieje konwersja rozpakowywanie z typu referencyjnego na bazowe non_nullable_value_type 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.

Typ wartości S ma rozpakowywanie konwersji z typu interfejsu I , jeśli ma ona konwersję rozpakowywanie z typu interfejsu I0 i I0 ma konwersję tożsamości na 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.

Typ wartości S ma rozpakowywanie konwersji z typu interfejsu, I Jeśli ma konwersję rozpakowywania z interfejsu lub typu delegata I0 , a I0 jest to WARIANCJA do konwersji wariancji I na I I0 (Konwersja wariancji).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).

Operacja rozpakowywania polega na pierwszym sprawdzeniu, że wystąpienie obiektu jest wartością opakowaną danego value_type, a następnie kopiując wartość z wystąpienia.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. Rozpakowywanie odwołania o wartości null do nullable_type powoduje utworzenie wartości null nullable_type.Unboxing a null reference to a nullable_type produces the null value of the nullable_type. Struktura może być oddzielna od typu System.ValueType , ponieważ jest klasą bazową dla wszystkich struktur (dziedziczenie).A struct can be unboxed from the type System.ValueType, since that is a base class for all structs (Inheritance).

Konwersje rozpakowywania są szczegółowo opisane w konwersjirozpakowywania.Unboxing conversions are described further in Unboxing conversions.

Jawne konwersje dynamiczneExplicit dynamic conversions

Jawna konwersja dynamiczna istnieje na podstawie wyrażenia typu dynamic dla dowolnego typu T .An explicit dynamic conversion exists from an expression of type dynamic to any type T. Konwersja jest powiązana dynamicznie (powiązanie dynamiczne), co oznacza, że jawna konwersja zostanie poszukiwana w czasie wykonywania z typu wyrażenia do 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. Jeśli konwersja nie zostanie znaleziona, zostanie zgłoszony wyjątek czasu wykonywania.If no conversion is found, a run-time exception is thrown.

Jeśli dynamiczne powiązanie konwersji nie jest wymagane, można najpierw przekonwertować wyrażenie na object , a następnie na żądany typ.If dynamic binding of the conversion is not desired, the expression can be first converted to object, and then to the desired type.

Załóżmy, że zdefiniowano następującą klasę: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));
    }
}

Poniższy przykład ilustruje jawne konwersje dynamiczne: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

Najlepsza konwersja do programu o C jest znaleziona w czasie kompilacji, która jest jawną konwersją referencyjną.The best conversion of o to C is found at compile-time to be an explicit reference conversion. To nie powiedzie się w czasie wykonywania, ponieważ "1" nie jest w rzeczywistości C .This fails at run-time, because "1" is not in fact a C. Konwersja do programu d w taki C sposób, jak jawna konwersja dynamiczna, jest zawieszona do czasu wykonywania, gdzie zdefiniowana przez użytkownika konwersja z typu d -- string --do C zostanie znaleziona i powiedzie się.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.

Jawne konwersje obejmujące parametry typuExplicit conversions involving type parameters

Następujące Konwersje jawne istnieją dla danego parametru typu T :The following explicit conversions exist for a given type parameter T:

  • Od obowiązującej klasy bazowej C T do T i z dowolnej klasy podstawowej C do T .From the effective base class C of T to T and from any base class of C to T. W czasie wykonywania, jeśli T jest typem wartości, konwersja jest wykonywana jako konwersja rozpakowywanie.At run-time, if T is a value type, the conversion is executed as an unboxing conversion. W przeciwnym razie konwersja jest wykonywana jako jawna konwersja odwołania lub konwersja tożsamości.Otherwise, the conversion is executed as an explicit reference conversion or identity conversion.
  • Z dowolnego typu interfejsu do T .From any interface type to T. W czasie wykonywania, jeśli T jest typem wartości, konwersja jest wykonywana jako konwersja rozpakowywanie.At run-time, if T is a value type, the conversion is executed as an unboxing conversion. W przeciwnym razie konwersja jest wykonywana jako jawna konwersja odwołania lub konwersja tożsamości.Otherwise, the conversion is executed as an explicit reference conversion or identity conversion.
  • Od T do dowolnych INTERFACE_TYPE , w przypadku których I nie istnieje jeszcze niejawna konwersja z T do I .From T to any interface_type I provided there is not already an implicit conversion from T to I. W czasie wykonywania, jeśli T jest typem wartości, konwersja jest wykonywana jako konwersja z opakowania, po którym następuje jawna konwersja odwołania.At run-time, if T is a value type, the conversion is executed as a boxing conversion followed by an explicit reference conversion. W przeciwnym razie konwersja jest wykonywana jako jawna konwersja odwołania lub konwersja tożsamości.Otherwise, the conversion is executed as an explicit reference conversion or identity conversion.
  • Z parametru typu U do T , dostarczony jest T zależny od U (ograniczenia parametru typu).From a type parameter U to T, provided T depends on U (Type parameter constraints). W czasie wykonywania, jeśli U jest typem wartości, T i jest U koniecznie tego samego typu, a konwersja nie jest przeprowadzana.At run-time, if U is a value type, then T and U are necessarily the same type and no conversion is performed. W przeciwnym razie, jeśli T jest typem wartości, konwersja jest wykonywana jako konwersja rozpakowywanie.Otherwise, if T is a value type, the conversion is executed as an unboxing conversion. W przeciwnym razie konwersja jest wykonywana jako jawna konwersja odwołania lub konwersja tożsamości.Otherwise, the conversion is executed as an explicit reference conversion or identity conversion.

Jeśli T jest znany jako typ referencyjny, powyższe konwersje są wszystkie sklasyfikowane jako jawne konwersje odwołań (jawne konwersje odwołań).If T is known to be a reference type, the conversions above are all classified as explicit reference conversions (Explicit reference conversions). Jeśli T nie jest to typ referencyjny, powyższe konwersje są klasyfikowane jako konwersje rozpakowywania (konwersje rozpakowywanie).If T is not known to be a reference type, the conversions above are classified as unboxing conversions (Unboxing conversions).

Powyższe zasady nie zezwalają na bezpośrednią jawną konwersję z nieograniczonego parametru typu do typu innego niż interfejs, który może być zaskakujące.The above rules do not permit a direct explicit conversion from an unconstrained type parameter to a non-interface type, which might be surprising. Przyczyną tej reguły jest zapobieganie nieporozumieniu i wykonywanie semantyki takich konwersji.The reason for this rule is to prevent confusion and make the semantics of such conversions clear. Na przykład przeanalizujmy następującą deklarację:For example, consider the following declaration:

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

W przypadku, gdy bezpośrednia jawna konwersja t do elementu int była dozwolona, jeden może być łatwo oczekiwać, że X<int>.F(7) zwróci  7L .If the direct explicit conversion of t to int were permitted, one might easily expect that X<int>.F(7) would return 7L. Jednakże, ponieważ standardowe konwersje liczbowe są brane pod uwagę tylko wtedy, gdy typy są znane jako liczbowe w czasie trwania powiązania.However, it would not, because the standard numeric conversions are only considered when the types are known to be numeric at binding-time. Aby semantyka była oczywista, należy napisać powyższy przykład: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
    }
}

Ten kod zostanie teraz skompilowany, ale wykonanie X<int>.F(7) zwróci wyjątek w czasie wykonywania, ponieważ opakowany int nie można przekonwertować bezpośrednio do 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.

Jawne konwersje zdefiniowane przez użytkownikaUser-defined explicit conversions

Jawna konwersja zdefiniowana przez użytkownika składa się z opcjonalnej standardowej konwersji jawnej, po której następuje wykonanie zdefiniowanego przez użytkownika operatora konwersji jawnej lub jawnej, a następnie innej opcjonalnej konwersji jawnej.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. Dokładne reguły oceniania jawnych konwersji zdefiniowanych przez użytkownika są opisane w temacie Przetwarzanie konwersji jawnych zdefiniowanych przez użytkownika.The exact rules for evaluating user-defined explicit conversions are described in Processing of user-defined explicit conversions.

Konwersje standardoweStandard conversions

Standardowe konwersje są wstępnie zdefiniowanymi konwersjemi, które mogą wystąpić w ramach konwersji zdefiniowanej przez użytkownika.The standard conversions are those pre-defined conversions that can occur as part of a user-defined conversion.

Standardowe konwersje niejawneStandard implicit conversions

Następujące niejawne konwersje są klasyfikowane jako standardowe konwersje niejawne:The following implicit conversions are classified as standard implicit conversions:

Standardowe konwersje niejawne wykluczają specjalne konwersje niejawne zdefiniowane przez użytkownika.The standard implicit conversions specifically exclude user-defined implicit conversions.

Standardowe Konwersje jawneStandard explicit conversions

Standardowe Konwersje jawne to wszystkie standardowe konwersje niejawne oraz podzestaw jawnych konwersji, dla których istnieje odwrotna niejawna konwersja.The standard explicit conversions are all standard implicit conversions plus the subset of the explicit conversions for which an opposite standard implicit conversion exists. Innymi słowy, jeśli standardowa niejawna konwersja istnieje z typu A do typu B , wówczas standardowa jawna konwersja istnieje z typu A do typ B i od typu B do typu 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.

Konwersje zdefiniowane przez użytkownikaUser-defined conversions

Język C# umożliwia wstępne Definiowanie konwersji niejawnych i jawnych przez zdefiniowane przez użytkownika Konwersje.C# allows the pre-defined implicit and explicit conversions to be augmented by user-defined conversions. Konwersje zdefiniowane przez użytkownika są wprowadzane przez deklarując operatory konwersji (Operatory konwersji) w typach klasy i struktury.User-defined conversions are introduced by declaring conversion operators (Conversion operators) in class and struct types.

Dozwolone konwersje zdefiniowane przez użytkownikaPermitted user-defined conversions

Język C# zezwala na zadeklarowanie tylko określonych konwersji zdefiniowanych przez użytkownika.C# permits only certain user-defined conversions to be declared. W szczególności nie jest możliwe ponowne zdefiniowanie istniejącej konwersji niejawnej lub jawnej.In particular, it is not possible to redefine an already existing implicit or explicit conversion.

Dla danego typu źródła S i typu docelowego T , jeśli S lub T dopuszczają wartości null, pozwól S0 i T0 odwołują się do ich typów podstawowych, w przeciwnym razie S0 i T0 są równe S i T odpowiednio.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. Klasa lub struktura jest dozwolona do deklarowania konwersji z typu źródłowego S na typ docelowy T tylko wtedy, gdy spełnione są wszystkie następujące warunki: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 i T0 są różnymi typami.S0 and T0 are different types.
  • S0Lub T0 jest klasą lub typem struktury, w której odbywa się deklaracja operatora.Either S0 or T0 is the class or struct type in which the operator declaration takes place.
  • Ani S0 nie T0 jest INTERFACE_TYPE.Neither S0 nor T0 is an interface_type.
  • Z wyjątkiem konwersji zdefiniowanych przez użytkownika, konwersja nie istnieje z S do T lub z T do S .Excluding user-defined conversions, a conversion does not exist from S to T or from T to S.

Ograniczenia dotyczące konwersji zdefiniowanych przez użytkownika są szczegółowo omówione w operatorach konwersji.The restrictions that apply to user-defined conversions are discussed further in Conversion operators.

Przenoszone operatory konwersjiLifted conversion operators

Po zdefiniowaniu zdefiniowanego przez użytkownika operatora konwersji, który konwertuje z niedopuszczający wartości null typ wartości S na wartość niezerową T , przenoszone Operator konwersji istnieje, który konwertuje z S? do 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?. Ten przekształcony Operator konwersji wykonuje odpakowanie od S? do S , po którym następuje konwersja zdefiniowana przez użytkownika z S T elementu do, po którym następuje Zawijanie z T do T? , z tą różnicą, że wartość null jest S? konwertowana bezpośrednio do wartości null T? .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?.

Przenoszone operatory konwersji mają tę samą niejawną lub niejawną klasyfikację, jak jej podstawowy zdefiniowany przez użytkownika Operator konwersji.A lifted conversion operator has the same implicit or explicit classification as its underlying user-defined conversion operator. Termin "konwersja zdefiniowana przez użytkownika" dotyczy użycia operatorów konwersji zdefiniowanych przez użytkownika i podnoszenia.The term "user-defined conversion" applies to the use of both user-defined and lifted conversion operators.

Obliczanie konwersji zdefiniowanych przez użytkownikaEvaluation of user-defined conversions

Zdefiniowana przez użytkownika konwersja konwertuje wartość z typu o nazwie Source Type _ do innego typu, zwanego _typem docelowym*.A user-defined conversion converts a value from its type, called the source type _, to another type, called the _target type*. Obliczanie zdefiniowanych przez użytkownika centrów konwersji na potrzeby wyszukiwania _ najbardziej określonego* zdefiniowanego przez użytkownika operatora konwersji dla określonych typów źródłowych i docelowych.Evaluation of a user-defined conversion centers on finding the _ most specific* user-defined conversion operator for the particular source and target types. To oznaczenie jest podzielone na kilka kroków:This determination is broken into several steps:

  • Znajdowanie zestawu klas i struktur, z których będą brane operatory konwersji zdefiniowane przez użytkownika.Finding the set of classes and structs from which user-defined conversion operators will be considered. Ten zestaw składa się z typu źródła i jego klas bazowych oraz typu docelowego i jego klas bazowych (z niejawnymi założeniami, które tylko klasy i struktury mogą deklarować operatorów zdefiniowanych przez użytkownika, a typy nieklasowe nie mają klas bazowych).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). Na potrzeby tego kroku, jeśli typem źródłowym lub docelowym jest nullable_type, zamiast niego zostanie użyty ich typ podstawowy.For the purposes of this step, if either the source or target type is a nullable_type, their underlying type is used instead.
  • Z tego zestawu typów można określić, które operatory konwersji zdefiniowane przez użytkownika i przenoszone.From that set of types, determining which user-defined and lifted conversion operators are applicable. Aby operator konwersji miał zastosowanie, musi być możliwe wykonanie konwersji standardowej (Konwersje standardowe) z typu źródłowego na typ operandu operatora i musi być możliwe wykonanie konwersji standardowej z typu wynikowego operatora na typ docelowy.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.
  • Z zestawu odpowiednich operatorów zdefiniowanych przez użytkownika, określający, który operator jest jednoznacznie najbardziej specyficzny.From the set of applicable user-defined operators, determining which operator is unambiguously the most specific. Ogólnie rzecz biorąc, najbardziej konkretny operator jest operatorem, którego typ operandu jest "najbliższy" do typu źródłowego i którego typ wyniku to "najbliższy" do typu docelowego.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. Zdefiniowane przez użytkownika operatory konwersji są preferowane przez przenoszone operatory konwersji.User-defined conversion operators are preferred over lifted conversion operators. Dokładne reguły dotyczące ustanawiania najbardziej określonego zdefiniowanego przez użytkownika operatora konwersji są zdefiniowane w poniższych sekcjach.The exact rules for establishing the most specific user-defined conversion operator are defined in the following sections.

Po zidentyfikowaniu określonego zdefiniowanego przez użytkownika operatora konwersji rzeczywiste wykonanie konwersji zdefiniowanej przez użytkownika obejmuje trzy kroki:Once a most specific user-defined conversion operator has been identified, the actual execution of the user-defined conversion involves up to three steps:

  • Po pierwsze, w razie potrzeby, przeprowadzenie konwersji standardowej z typu źródłowego na typ operandu operatora konwersji zdefiniowanego przez użytkownika lub podnoszenia.First, if required, performing a standard conversion from the source type to the operand type of the user-defined or lifted conversion operator.
  • Następnie wywoływanie operatora konwersji zdefiniowanego przez użytkownika lub zniesionego w celu przeprowadzenia konwersji.Next, invoking the user-defined or lifted conversion operator to perform the conversion.
  • Na koniec, w razie potrzeby, przeprowadzenie standardowej konwersji z typu wynikowego operatora konwersji zdefiniowanego przez użytkownika lub przekształcenia na typ docelowy.Finally, if required, performing a standard conversion from the result type of the user-defined or lifted conversion operator to the target type.

Obliczanie zdefiniowanej przez użytkownika konwersji nigdy nie obejmuje więcej niż jednego operatora konwersji zdefiniowanego przez użytkownika lub podniesionego.Evaluation of a user-defined conversion never involves more than one user-defined or lifted conversion operator. Innymi słowy konwersja z typu S do typu T nigdy nie wykonuje najpierw konwersji zdefiniowanej przez użytkownika z S na X , a następnie wykonuje konwersję zdefiniowaną przez użytkownika z X do 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.

Dokładne definicje oceny niejawnych lub jawnych konwersji zdefiniowanych przez użytkownika są podano w poniższych sekcjach.Exact definitions of evaluation of user-defined implicit or explicit conversions are given in the following sections. Definicje korzystają z następujących warunków:The definitions make use of the following terms:

  • Jeśli standardowa niejawna konwersja (konwersje niejawne standardowe) istnieje z typu A do typu B , a jeśli nie, ani nie A B jest INTERFACE_TYPE s, wówczas A jest określana jako * połączona przez _ B i B jest określana jako _ ** * 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_type s, then A is said to be encompassed by _ B, and B is said to _ encompass A.
  • Najbardziej obejmujący typ w zestawie typów to jeden typ, który obejmuje wszystkie inne typy w zestawie.The most encompassing type in a set of types is the one type that encompasses all other types in the set. Jeśli żaden typ pojedynczy nie obejmuje wszystkich innych typów, zestaw nie ma żadnego typu obejmującego.If no single type encompasses all other types, then the set has no most encompassing type. W bardziej intuicyjnych warunkach, najbardziej obejmujący typ to "największy" typ w zestawie — jeden typ, do którego każdy inny typ może być niejawnie konwertowany.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.
  • Najbardziej pożądany Typ w zestawie typów to jeden typ, który jest obejmujący wszystkie inne typy w zestawie.The most encompassed type in a set of types is the one type that is encompassed by all other types in the set. Jeśli żaden typ pojedynczy nie zostanie określony przez wszystkie inne typy, zestaw nie ma żadnego typu z typem.If no single type is encompassed by all other types, then the set has no most encompassed type. W bardziej intuicyjnych warunkach, najbardziej odnoszące się do typu "najmniejszy" typ w zestawie — jeden typ, który może być niejawnie konwertowany na każdy z innych typów.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.

Przetwarzanie konwersji niejawnych zdefiniowanych przez użytkownikaProcessing of user-defined implicit conversions

Zdefiniowana przez użytkownika niejawna konwersja z typu S na typ T jest przetwarzana w następujący sposób:A user-defined implicit conversion from type S to type T is processed as follows:

  • Określ typy S0 i T0 .Determine the types S0 and T0. Jeśli S lub T jest typem dopuszczającym wartość null, S0 i T0 są ich typami podstawowymi, w przeciwnym razie S0 i T0 są równe S i T odpowiednio.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.
  • Znajdź zestaw typów, D z którego będą brane pod uwagę operatory konwersji zdefiniowane przez użytkownika.Find the set of types, D, from which user-defined conversion operators will be considered. Ten zestaw składa się z S0 (Jeśli S0 jest klasą lub strukturą), klas bazowych S0 (Jeśli S0 jest klasą) i T0 (Jeśli T0 jest klasą lub strukturą).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).
  • Znajdź zestaw odpowiednich operatorów konwersji zdefiniowanych przez użytkownika i podnoszenia, U .Find the set of applicable user-defined and lifted conversion operators, U. Ten zestaw składa się z zdefiniowanych przez użytkownika i poddanych niejawnych operatorów konwersji zadeklarowanych przez klasy lub struktury w D tej konwersji z typu, który obejmuje typ obejmujący S 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. Jeśli U jest pusty, konwersja jest niezdefiniowana i wystąpi błąd w czasie kompilacji.If U is empty, the conversion is undefined and a compile-time error occurs.
  • Znajdź najbardziej konkretny typ źródła, SX dla operatorów w U :Find the most specific source type, SX, of the operators in U:
    • Jeśli którykolwiek z operatorów w U konwersji z S , to SX S .If any of the operators in U convert from S, then SX is S.
    • W przeciwnym razie SX jest to najbardziej pozostały typ w połączonym zestawie typów źródłowych operatorów w U .Otherwise, SX is the most encompassed type in the combined set of source types of the operators in U. Jeśli nie można znaleźć dokładnie jednego z najbardziej pokrytych typów, konwersja jest niejednoznaczna i wystąpi błąd w czasie kompilacji.If exactly one most encompassed type cannot be found, then the conversion is ambiguous and a compile-time error occurs.
  • Znajdź najbardziej konkretny typ docelowy, TX dla operatorów w U :Find the most specific target type, TX, of the operators in U:
    • Jeśli którykolwiek z operatorów w U konwersji na T , to TX T .If any of the operators in U convert to T, then TX is T.
    • W przeciwnym razie TX jest to najbardziej obejmujący typ w połączonym zestawie typów docelowych operatorów w U .Otherwise, TX is the most encompassing type in the combined set of target types of the operators in U. Jeśli nie można znaleźć dokładnie jednego typu, który nie zawiera, konwersja jest niejednoznaczna i wystąpi błąd kompilacji.If exactly one most encompassing type cannot be found, then the conversion is ambiguous and a compile-time error occurs.
  • Znajdź najbardziej specyficzny Operator konwersji:Find the most specific conversion operator:
    • Jeśli U zawiera dokładnie jeden operator konwersji zdefiniowany przez użytkownika, który konwertuje z SX na TX , wówczas jest to najbardziej specyficzny Operator konwersji.If U contains exactly one user-defined conversion operator that converts from SX to TX, then this is the most specific conversion operator.
    • W przeciwnym razie, jeśli U zawiera dokładnie jeden podnieśny Operator konwersji, który konwertuje z SX na TX , wówczas jest to najbardziej specyficzny Operator konwersji.Otherwise, if U contains exactly one lifted conversion operator that converts from SX to TX, then this is the most specific conversion operator.
    • W przeciwnym razie konwersja jest niejednoznaczna i wystąpi błąd w czasie kompilacji.Otherwise, the conversion is ambiguous and a compile-time error occurs.
  • Na koniec zastosuj konwersję:Finally, apply the conversion:
    • Jeśli S nie jest SX , zostanie przeprowadzona standardowa niejawna konwersja z S na SX .If S is not SX, then a standard implicit conversion from S to SX is performed.
    • Najbardziej specyficzny Operator konwersji jest wywoływany do konwersji z SX na TX .The most specific conversion operator is invoked to convert from SX to TX.
    • Jeśli TX nie jest T , zostanie przeprowadzona standardowa niejawna konwersja z TX na T .If TX is not T, then a standard implicit conversion from TX to T is performed.

Przetwarzanie konwersji jawnych zdefiniowanych przez użytkownikaProcessing of user-defined explicit conversions

Jawna konwersja zdefiniowana przez użytkownika z typu S na typ T jest przetwarzana w następujący sposób:A user-defined explicit conversion from type S to type T is processed as follows:

  • Określ typy S0 i T0 .Determine the types S0 and T0. Jeśli S lub T jest typem dopuszczającym wartość null, S0 i T0 są ich typami podstawowymi, w przeciwnym razie S0 i T0 są równe S i T odpowiednio.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.
  • Znajdź zestaw typów, D z którego będą brane pod uwagę operatory konwersji zdefiniowane przez użytkownika.Find the set of types, D, from which user-defined conversion operators will be considered. Ten zestaw składa się z S0 (Jeśli S0 jest klasą lub strukturą), klas bazowych S0 (Jeśli S0 jest klasą), T0 (jeśli jest klasą T0 lub strukturą) i klasami podstawowymi T0 (Jeśli T0 jest klasą).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).
  • Znajdź zestaw odpowiednich operatorów konwersji zdefiniowanych przez użytkownika i podnoszenia, U .Find the set of applicable user-defined and lifted conversion operators, U. Ten zestaw składa się z zdefiniowanych przez użytkownika i podnoszenia niejawnych lub jawnych operatorów konwersji zadeklarowanych przez klasy lub struktury w D tej konwersji z typu, który obejmuje lub obejmuje S Typ obejmujący lub obejmujący 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. Jeśli U jest pusty, konwersja jest niezdefiniowana i wystąpi błąd w czasie kompilacji.If U is empty, the conversion is undefined and a compile-time error occurs.
  • Znajdź najbardziej konkretny typ źródła, SX dla operatorów w U :Find the most specific source type, SX, of the operators in U:
    • Jeśli którykolwiek z operatorów w U konwersji z S , to SX S .If any of the operators in U convert from S, then SX is S.
    • W przeciwnym razie, jeśli którykolwiek z operatorów w U konwersji z typów, które obejmują S , SX jest najbardziej powiązanego typu w połączonym zestawie typów źródłowych tych operatorów.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. Jeśli nie można znaleźć typu z większością typów, konwersja jest niejednoznaczna i wystąpi błąd w czasie kompilacji.If no most encompassed type can be found, then the conversion is ambiguous and a compile-time error occurs.
    • W przeciwnym razie SX jest to najbardziej obejmujący typ w połączonym zestawie typów źródła operatorów w U .Otherwise, SX is the most encompassing type in the combined set of source types of the operators in U. Jeśli nie można znaleźć dokładnie jednego typu, który nie zawiera, konwersja jest niejednoznaczna i wystąpi błąd kompilacji.If exactly one most encompassing type cannot be found, then the conversion is ambiguous and a compile-time error occurs.
  • Znajdź najbardziej konkretny typ docelowy, TX dla operatorów w U :Find the most specific target type, TX, of the operators in U:
    • Jeśli którykolwiek z operatorów w U konwersji na T , to TX T .If any of the operators in U convert to T, then TX is T.
    • W przeciwnym razie, jeśli którykolwiek z operatorów w U konwersji na typy, które są objęte przez T , TX to najbardziej obejmujący typ w połączonym zestawie typów docelowych tych operatorów.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. Jeśli nie można znaleźć dokładnie jednego typu, który nie zawiera, konwersja jest niejednoznaczna i wystąpi błąd kompilacji.If exactly one most encompassing type cannot be found, then the conversion is ambiguous and a compile-time error occurs.
    • W przeciwnym razie TX jest to najbardziej pozostały typ w połączonym zestawie typów docelowych operatorów w U .Otherwise, TX is the most encompassed type in the combined set of target types of the operators in U. Jeśli nie można znaleźć typu z większością typów, konwersja jest niejednoznaczna i wystąpi błąd w czasie kompilacji.If no most encompassed type can be found, then the conversion is ambiguous and a compile-time error occurs.
  • Znajdź najbardziej specyficzny Operator konwersji:Find the most specific conversion operator:
    • Jeśli U zawiera dokładnie jeden operator konwersji zdefiniowany przez użytkownika, który konwertuje z SX na TX , wówczas jest to najbardziej specyficzny Operator konwersji.If U contains exactly one user-defined conversion operator that converts from SX to TX, then this is the most specific conversion operator.
    • W przeciwnym razie, jeśli U zawiera dokładnie jeden podnieśny Operator konwersji, który konwertuje z SX na TX , wówczas jest to najbardziej specyficzny Operator konwersji.Otherwise, if U contains exactly one lifted conversion operator that converts from SX to TX, then this is the most specific conversion operator.
    • W przeciwnym razie konwersja jest niejednoznaczna i wystąpi błąd w czasie kompilacji.Otherwise, the conversion is ambiguous and a compile-time error occurs.
  • Na koniec zastosuj konwersję:Finally, apply the conversion:
    • Jeśli S nie jest SX , to wykonywana jest standardowa jawna konwersja z S do SX .If S is not SX, then a standard explicit conversion from S to SX is performed.
    • Najbardziej szczegółowy zdefiniowany przez użytkownika Operator konwersji jest wywoływany do konwersji z SX do TX .The most specific user-defined conversion operator is invoked to convert from SX to TX.
    • Jeśli TX nie jest T , to wykonywana jest standardowa jawna konwersja z TX do T .If TX is not T, then a standard explicit conversion from TX to T is performed.

Konwersje funkcji anonimowychAnonymous function conversions

Anonymous_method_expression lub lambda_expression są klasyfikowane jako funkcja anonimowa (wyrażenia funkcji anonimowych).An anonymous_method_expression or lambda_expression is classified as an anonymous function (Anonymous function expressions). Wyrażenie nie ma typu, ale może być niejawnie konwertowane na zgodny typ delegata lub typ drzewa wyrażenia.The expression does not have a type but can be implicitly converted to a compatible delegate type or expression tree type. W specjalnej postaci funkcja anonimowa F jest zgodna z podanym typem delegata D :Specifically, an anonymous function F is compatible with a delegate type D provided:

  • Jeśli F zawiera anonymous_function_signature, a następnie D ma taką F samą liczbę parametrów.If F contains an anonymous_function_signature, then D and F have the same number of parameters.
  • Jeśli nie F zawiera anonymous_function_signature, wówczas D może być zero lub więcej parametrów dowolnego typu, o ile żaden parametr D ma out modyfikator parametru.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.
  • Jeśli F ma jawnie wpisaną listę parametrów, każdy parametr w D ma ten sam typ i Modyfikatory co odpowiedni parametr w 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.
  • Jeśli F ma niejawnie wpisaną listę parametrów, D nie ma ref out parametrów ani.If F has an implicitly typed parameter list, D has no ref or out parameters.
  • Jeśli treść F jest wyrażeniem, a D ma void zwracany typ lub F jest Async i D ma zwracany typ Task , a następnie gdy każdy parametr F jest przyznany typ odpowiadającego parametru w D , treść F jest prawidłowym wyrażeniem ( wyrażeniaWRT), które byłyby dozwolone jako statement_expression (instrukcje wyrażeń).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).
  • Jeśli treść F jest blokiem instrukcji i D ma void zwracany typ lub F jest Async i D ma zwracany typ Task , a następnie, gdy każdy parametr F jest przyznany typ odpowiadającego parametru w D , treść F jest prawidłowym blokiem instrukcji ( blokiWRT), w którym żadna return instrukcja nie określa wyrażenia.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.
  • Jeśli treść F jest wyrażeniem, a nie F jest Async i D ma typ inny niż void T , lub F jest Async i D ma zwracany typ Task<T> , a następnie, gdy każdy z parametrów F ma typ odpowiedniego parametru w D , treść F jest prawidłowym wyrażeniem ( wyrażeniaWRT), które jest niejawnie konwertowane na 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.
  • Jeśli treść F jest bloku instrukcji, i F jest nieasync i D ma typ inny niż void T lub F jest Async i D ma zwracany typ Task<T> , a następnie, gdy każdy parametr F jest przyznany typ odpowiadającego parametru w D , treść F jest prawidłowym blokiem instrukcji ( blokiWRT) z nieosiągalnym punktem końcowym, w którym każda return instrukcja określa wyrażenie, które jest niejawnie konwertowane na 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.

Na potrzeby zwięzłości Ta sekcja używa krótkiej formy typów zadań Task i Task<T> (funkcje asynchroniczne).For the purpose of brevity, this section uses the short form for the task types Task and Task<T> (Async functions).

Wyrażenie lambda F jest zgodne z typem drzewa wyrażenia, Expression<D> Jeśli F jest zgodne z typem delegata D .A lambda expression F is compatible with an expression tree type Expression<D> if F is compatible with the delegate type D. Należy zauważyć, że nie dotyczy to metod anonimowych, tylko wyrażeń lambda.Note that this does not apply to anonymous methods, only lambda expressions.

Niektóre wyrażenia lambda nie mogą być konwertowane na typy drzewa wyrażeń: nawet jeśli konwersja istnieje, kończy się niepowodzeniem w czasie kompilacji.Certain lambda expressions cannot be converted to expression tree types: Even though the conversion exists, it fails at compile-time. Dzieje się tak, jeśli wyrażenie lambda:This is the case if the lambda expression:

  • Ma treść blokuHas a block body
  • Zawiera proste lub złożone operatory przypisaniaContains simple or compound assignment operators
  • Zawiera dynamiczne wyrażenie powiązaneContains a dynamically bound expression
  • Jest asynchronicznyIs async

Poniższe przykłady używają ogólnego typu delegata, Func<A,R> który reprezentuje funkcję, która przyjmuje argument typu A i zwraca wartość typu 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);

W przypisaniachIn 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

parametry i zwracane typy każdej funkcji anonimowej są określane na podstawie typu zmiennej, do której jest przypisana funkcja anonimowa.the parameter and return types of each anonymous function are determined from the type of the variable to which the anonymous function is assigned.

Pierwsze przypisanie pomyślnie konwertuje funkcję anonimową na typ delegata Func<int,int> , ponieważ, gdy x ma dany typ int , x+1 jest prawidłowym wyrażeniem, które jest niejawnie konwertowane na typ 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.

Podobnie drugie przypisanie pomyślnie konwertuje funkcję anonimową na typ delegata, Func<int,double> ponieważ wynik x+1 (typu int ) jest niejawnie konwertowany na typ 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.

Jednak trzecie przypisanie to błąd czasu kompilacji, ponieważ w przypadku x danego typu double wynik x+1 (typu double ) nie jest niejawnie konwertowany na typ 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.

Czwarte przypisanie pomyślnie konwertuje anonimową funkcję asynchroniczną na typ delegata, Func<int, Task<int>> ponieważ wynik x+1 (typu int ) jest niejawnie konwertowany na typ wynikowy int typu zadania 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>.

Funkcje anonimowe mogą mieć wpływ na rozwiązanie przeciążania i uczestniczyć w wnioskach o typie.Anonymous functions may influence overload resolution, and participate in type inference. Aby uzyskać więcej informacji, zobacz elementy członkowskie funkcji .See Function members for further details.

Obliczanie konwersji funkcji anonimowych na typy delegatówEvaluation of anonymous function conversions to delegate types

Konwersja funkcji anonimowej na typ delegata tworzy wystąpienie delegata, które odwołuje się do funkcji anonimowej i (prawdopodobnie puste) zestaw przechwyconych zmiennych zewnętrznych, które są aktywne w czasie szacowania.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. Gdy obiekt delegowany jest wywoływany, jest wykonywana treść funkcji anonimowej.When the delegate is invoked, the body of the anonymous function is executed. Kod w treści jest wykonywany przy użyciu zestawu przechwyconych zmiennych zewnętrznych, do których odwołuje się delegat.The code in the body is executed using the set of captured outer variables referenced by the delegate.

Lista wywołań delegata utworzonego na podstawie funkcji anonimowej zawiera pojedynczy wpis.The invocation list of a delegate produced from an anonymous function contains a single entry. Nie określono dokładnego obiektu docelowego i docelowej metody delegata.The exact target object and target method of the delegate are unspecified. W szczególności nie określono, czy obiekt docelowy delegata jest null , this wartość otaczającego elementu członkowskiego funkcji lub innego obiektu.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.

Konwersje semantycznie identycznych funkcji anonimowych z tym samym (prawdopodobnie pustym) zestawem przechwyconych wystąpień zmiennych zewnętrznych do tych samych typów delegatów są dozwolone (ale nie są wymagane) do zwrócenia tego samego wystąpienia delegata.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. Termin o wartości semantycznie jest używany w tym miejscu do oznaczania, że wykonanie funkcji anonimowych będzie we wszystkich przypadkach dawać te same skutki mające te same argumenty.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. Ta reguła umożliwia zoptymalizowanie kodu, takiego jak poniższe.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));
        ...
    }
}

Ponieważ dwie Delegaty funkcji anonimowych mają ten sam (pusty) zbiór przechwyconych zmiennych zewnętrznych i ponieważ funkcje anonimowe są semantycznie identyczne, kompilator może odwoływać się do tej samej metody docelowej.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. W rzeczywistości kompilator może zwrócić to samo wystąpienie delegata z obu wyrażeń funkcji anonimowej.Indeed, the compiler is permitted to return the very same delegate instance from both anonymous function expressions.

Obliczanie konwersji funkcji anonimowych na typy drzewa wyrażeńEvaluation of anonymous function conversions to expression tree types

Konwersja funkcji anonimowej na typ drzewa wyrażenia tworzy drzewo wyrażenia (Typy drzewa wyrażeń).Conversion of an anonymous function to an expression tree type produces an expression tree (Expression tree types). Dokładniejsze Obliczanie konwersji funkcji anonimowych prowadzi do konstrukcji struktury obiektu, która reprezentuje strukturę samej funkcji anonimowej.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. Precyzyjna struktura drzewa wyrażenia, a także dokładny proces tworzenia go, to implementacja zdefiniowana.The precise structure of the expression tree, as well as the exact process for creating it, are implementation defined.

Przykład implementacjiImplementation example

W tej sekcji opisano możliwe implementację konwersji funkcji anonimowych w odniesieniu do innych konstrukcji języka C#.This section describes a possible implementation of anonymous function conversions in terms of other C# constructs. Implementacja opisana tutaj jest oparta na tych samych zasadach, które są używane przez kompilator języka C# firmy Microsoft, ale nie oznacza to, że jest to dozwolone wdrożenie, ani nie jest to jedyna możliwa.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. Zawiera krótkie informacje tylko o konwersjach na drzewa wyrażeń, ponieważ ich dokładna semantyka wykracza poza zakres tej specyfikacji.It only briefly mentions conversions to expression trees, as their exact semantics are outside the scope of this specification.

W pozostałej części tej sekcji przedstawiono kilka przykładów kodu, który zawiera anonimowe funkcje o różnych właściwościach.The remainder of this section gives several examples of code that contains anonymous functions with different characteristics. Dla każdego przykładu podano odpowiednie tłumaczenie dla kodu, który używa tylko innych konstrukcji języka C#.For each example, a corresponding translation to code that uses only other C# constructs is provided. W przykładach identyfikator D jest założono przez reprezentuje następujący typ delegata:In the examples, the identifier D is assumed by represent the following delegate type:

public delegate void D();

Najprostsza forma funkcji anonimowej to taka, która nie przechwytuje żadnych zmiennych zewnętrznych:The simplest form of an anonymous function is one that captures no outer variables:

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

Można to przetłumaczyć na wystąpienie delegata, który odwołuje się do metody statycznej wygenerowanej przez kompilator, w której umieszczony jest kod funkcji anonimowej: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");
    }
}

W poniższym przykładzie funkcja anonimowa odwołuje się do członków wystąpienia this :In the following example, the anonymous function references instance members of this:

class Test
{
    int x;

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

Można to przetłumaczyć na metodę wystąpienia wygenerowanego przez kompilator zawierający kod funkcji anonimowej: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);
    }
}

W tym przykładzie funkcja anonimowa przechwytuje zmienną lokalną:In this example, the anonymous function captures a local variable:

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

Okres istnienia zmiennej lokalnej musi zostać przedłużony do co najmniej okresu istnienia delegata funkcji anonimowej.The lifetime of the local variable must now be extended to at least the lifetime of the anonymous function delegate. Można to osiągnąć przez "podnoszenia" zmiennej lokalnej do pola klasy wygenerowanej przez kompilator.This can be achieved by "hoisting" the local variable into a field of a compiler generated class. Utworzenie wystąpienia zmiennej lokalnej (utworzenie wystąpieniazmiennych lokalnych) odpowiada za utworzenie wystąpienia klasy wygenerowanej przez kompilator i uzyskanie dostępu do zmiennej lokalnej odpowiada na dostęp do pola w wystąpieniu klasy wygenerowanej przez kompilator.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. Ponadto funkcja anonimowa jest metodą wystąpienia klasy wygenerowanej przez kompilator: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);
        }
    }
}

Na koniec następująca funkcja anonimowa przechwytuje this również dwie zmienne lokalne o różnych okresach istnienia: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); };
        }
    }
}

W tym przykładzie Klasa wygenerowana przez kompilator jest tworzona dla każdego bloku instrukcji, w którym są przechwytywane elementy lokalne, tak że lokalne w różnych blokach mogą mieć niezależne okresy istnienia.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. Wystąpienie __Locals2 klasy wygenerowanej przez kompilator dla wewnętrznego bloku instrukcji, zawiera zmienną lokalną z i pole odwołujące się do wystąpienia __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. Wystąpienie __Locals1 klasy, wygenerowanej przez kompilator dla bloku instrukcji zewnętrznych, zawiera zmienną lokalną y i pole, które odwołuje this się do otaczającego elementu członkowskiego funkcji.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. Dzięki tym strukturom danych możliwe jest osiągnięcie wszystkich przechwyconych zmiennych zewnętrznych za pomocą wystąpienia __Local2 , a kod funkcji anonimowej może zostać zaimplementowany jako metoda wystąpienia tej klasy.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);
        }
    }
}

Ta sama technika zastosowana w tym miejscu do przechwytywania zmiennych lokalnych może być również używana podczas konwertowania funkcji anonimowych na drzewa wyrażeń: odwołania do obiektów generowanych przez kompilator mogą być przechowywane w drzewie wyrażenia, a dostęp do zmiennych lokalnych może być reprezentowany przez pola dostęp do tych obiektów.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. Zaletą tego podejścia jest umożliwienie współdzielenia "podnoszenia" zmiennych lokalnych między delegatami i drzewami wyrażeń.The advantage of this approach is that it allows the "lifted" local variables to be shared between delegates and expression trees.

Konwersje grup metodMethod group conversions

Niejawna konwersja (niejawne konwersje) istnieje z grupy metod (klasyfikacje wyrażeń) do zgodnego typu delegata.An implicit conversion (Implicit conversions) exists from a method group (Expression classifications) to a compatible delegate type. Mając typ delegata D i wyrażenie, E które jest sklasyfikowane jako grupa metod, niejawna konwersja istnieje E z do, D Jeśli E zawiera co najmniej jedną metodę, która jest stosowana w jego normalnej formie (odpowiedni element członkowski funkcji) do listy argumentów skonstruowanych za pomocą typów parametrów i modyfikatorów D , zgodnie z opisem w poniższej tabeli.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.

Aplikacja czasu kompilowania konwersji z grupy metod E do typu delegata D jest opisana w poniższej tabeli.The compile-time application of a conversion from a method group E to a delegate type D is described in the following. Należy zauważyć, że istnienie niejawnej konwersji z E do na D nie gwarantuje, że konwersja aplikacji czasu kompilowania zakończy się powodzeniem bez błędu.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.

  • Wybrana jest pojedyncza Metoda M odpowiadająca wywołaniu metody (wywołania metody) formularza E(A) , z następującymi modyfikacjami:A single method M is selected corresponding to a method invocation (Method invocations) of the form E(A), with the following modifications:
    • Lista argumentów A jest listą wyrażeń, z których każda została sklasyfikowana jako zmienna i z typem i modyfikatorem ( ref lub out ) odpowiadającego parametru w formal_parameter_list 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.
    • Metody kandydata są brane pod uwagę tylko te metody, które są stosowane w ich normalnej formie (element członkowski funkcji), a nie tylko w ich rozwiniętej postaci.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.
  • Jeśli algorytm wywołań metod wywołuje błąd, wystąpi błąd czasu kompilacji.If the algorithm of Method invocations produces an error, then a compile-time error occurs. W przeciwnym razie algorytm tworzy jedną najlepszą metodę M mającą taką samą liczbę parametrów jak D i konwersja jest uznawana za istnieje.Otherwise the algorithm produces a single best method M having the same number of parameters as D and the conversion is considered to exist.
  • Wybrana metoda M musi być zgodna (zgodność z delegatem) z typem delegata D lub w przeciwnym razie wystąpi błąd w czasie kompilacji.The selected method M must be compatible (Delegate compatibility) with the delegate type D, or otherwise, a compile-time error occurs.
  • Jeśli wybrana metoda M jest metodą wystąpienia, wyrażenie wystąpienia skojarzone z E określa obiekt docelowy delegata.If the selected method M is an instance method, the instance expression associated with E determines the target object of the delegate.
  • Jeśli wybrana metoda M jest metodą rozszerzenia, która jest oznaczona za pomocą dostępu do elementu członkowskiego w wyrażeniu wystąpienia, to wyrażenie wystąpienia określa obiekt docelowy delegata.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.
  • Wynikiem konwersji jest wartość typu  D , a mianowicie nowo utworzonego delegata, który odwołuje się do wybranej metody i obiektu docelowego.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.
  • Należy zauważyć, że ten proces może prowadzić do utworzenia delegata metody rozszerzenia, jeśli algorytm wywołania metody nie może znaleźć metody wystąpienia, ale kończy przetwarzanie wywołania E(A) jako wywołanie metody rozszerzenia (wywołania metody rozszerzenia).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). Delegat utworzony w ten sposób przechwytuje również metodę rozszerzenia oraz jej pierwszy argument.A delegate thus created captures the extension method as well as its first argument.

Poniższy przykład ilustruje konwersje grup metod: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

    }
}

Przypisanie do d1 niejawnie konwertuje grupę metod F na wartość typu D1 .The assignment to d1 implicitly converts the method group F to a value of type D1.

Przypisanie do d2 pokazuje, jak możliwe jest utworzenie delegata dla metody, która ma mniej pochodne typy parametrów (kontrawariantne) i bardziej pochodny typ zwracany (współvariant).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.

Przypisanie do d3 pokazuje, jak nie istnieje żadna konwersja, jeśli metoda nie ma zastosowania.The assignment to d3 shows how no conversion exists if the method is not applicable.

Przypisanie do d4 pokazuje, jak metoda musi być stosowana w jego normalnej postaci.The assignment to d4 shows how the method must be applicable in its normal form.

Przypisanie do d5 pokazuje, jak parametry i zwracane typy delegata i metody mogą się różnić tylko dla typów referencyjnych.The assignment to d5 shows how parameter and return types of the delegate and method are allowed to differ only for reference types.

Podobnie jak w przypadku wszystkich innych konwersji niejawnych i jawnych, operator rzutowania może służyć do jawnego wykonania konwersji grup metod.As with all other implicit and explicit conversions, the cast operator can be used to explicitly perform a method group conversion. W tym przykładzie przykładThus, the example

object obj = new EventHandler(myDialog.OkClick);

Zamiast tego może być zapisanycould instead be written

object obj = (EventHandler)myDialog.OkClick;

Grupy metod mogą mieć wpływ na rozwiązanie przeciążania i uczestniczyć w wnioskach o typie.Method groups may influence overload resolution, and participate in type inference. Aby uzyskać więcej informacji, zobacz elementy członkowskie funkcji .See Function members for further details.

Obliczanie w czasie wykonywania konwersji grup metod odbywa się w następujący sposób:The run-time evaluation of a method group conversion proceeds as follows:

  • Jeśli metoda wybrana w czasie kompilacji to metoda wystąpienia lub jest to metoda rozszerzająca, do której można uzyskać dostęp jako metoda wystąpienia, obiekt docelowy delegata jest określany na podstawie wyrażenia wystąpienia skojarzonego z 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:
    • Wyrażenie wystąpienia jest oceniane.The instance expression is evaluated. Jeśli ta Ocena spowoduje wyjątek, nie są wykonywane żadne dalsze kroki.If this evaluation causes an exception, no further steps are executed.
    • Jeśli wyrażenie wystąpienia ma reference_type, wartość obliczona przez wyrażenie wystąpienia zostaje obiektem docelowym.If the instance expression is of a reference_type, the value computed by the instance expression becomes the target object. Jeśli wybrana metoda jest metodą wystąpienia, a obiektem docelowym jest null , System.NullReferenceException jest zgłaszany i nie są wykonywane żadne dalsze kroki.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.
    • Jeśli wyrażenie wystąpienia ma value_type, operacja pakowania (konwersje z opakowania) jest wykonywana w celu przekonwertowania wartości na obiekt, a obiekt ten zostaje obiektem docelowym.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.
  • W przeciwnym razie wybrana metoda jest częścią wywołania metody statycznej, a obiektem docelowym delegata jest null .Otherwise the selected method is part of a static method call, and the target object of the delegate is null.
  • Zostanie przydzielono nowe wystąpienie typu delegata D .A new instance of the delegate type D is allocated. Jeśli nie ma wystarczającej ilości pamięci do przydzielenia nowego wystąpienia, System.OutOfMemoryException zgłaszany jest i nie są wykonywane żadne dalsze kroki.If there is not enough memory available to allocate the new instance, a System.OutOfMemoryException is thrown and no further steps are executed.
  • Nowe wystąpienie delegata jest inicjowane z odwołaniem do metody, która została określona w czasie kompilacji i odwołaniem do obiektu docelowego obliczonego powyżej.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.