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, a to określa, czy jest wymagane 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 longtypu.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 dynamici między tworzonymi typami, które są takie same podczas zastępowania 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, doublelub decimal.From sbyte to short, int, long, float, double, or decimal.
  • Z byte do short, ushort, int, uint, long, ulong, float, doublelub decimal.From byte to short, ushort, int, uint, long, ulong, float, double, or decimal.
  • Z short do int, long, float, doublelub decimal.From short to int, long, float, double, or decimal.
  • Z ushort do int, uint, long, ulong, float, doublelub decimal.From ushort to int, uint, long, ulong, float, double, or decimal.
  • Od int do long, float, doublelub decimal.From int to long, float, double, or decimal.
  • Z uint do long, ulong, float, doublelub decimal.From uint to long, ulong, float, double, or decimal.
  • Od long do float, doublelub decimal.From long to float, double, or decimal.
  • Od ulong do float, doublelub decimal.From ulong to float, double, or decimal.
  • Z char do ushort, int, uint, long, ulong, float, doublelub decimal.From char to ushort, int, uint, long, ulong, float, double, or decimal.
  • Z float double.From float to double.

Konwersje z int, uint, longlub ulong do float oraz od long lub ulong do double mogą spowodować utratę precyzji, ale nigdy nie spowoduje 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 typu char, dlatego wartości innych typów całkowitych nie są automatycznie konwertowane na typ char.There are no implicit conversions to the char type, so values of the other integral types do not automatically convert to the char type.

Niejawne konwersje wyliczeniaImplicit enumeration conversions

Niejawna konwersja Wyliczenie zezwala na konwersję decimal_integer_literal 0 na dowolną enum_type i nullable_type , których typem podstawowym 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 interpolowany) na System.IFormattable lub System.FormattableString (który implementuje 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. Zamiast tego tworzone jest wystąpienie System.FormattableString, 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 każdej wstępnie zdefiniowanej tożsamości niejawnej i konwersji liczbowych, które konwertują z typu wartości niedopuszczających wartości null S do Ttypu wartości niedopuszczających wartości null, 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 wartości null na podstawie bazowej konwersji z S na 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ścią źródłową jest 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 po niej bazowa konwersja z S do T, po którym następuje Zawijanie (Typy dopuszczające wartości null) od 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 do wartości null jest z S do T?, konwersja jest szacowana jako bazowa konwersja z S do T, a po nim otoka z T 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 w literale null do dowolnych typów dopuszczających 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 dowolnych reference_type do object i dynamic.From any reference_type to object and dynamic.
  • Z dowolnych S class_type do wszystkich class_type Tdostarczone S pochodzą z T.From any class_type S to any class_type T, provided S is derived from T.
  • Z dowolnego class_typeu S do dowolnego INTERFACE_TYPE Tpodano S implementuje T.From any class_type S to any interface_type T, provided S implements T.
  • Z dowolnych S INTERFACE_TYPE do wszystkich interface_type Tdostarczone S pochodzą z 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 T mają taką samą liczbę wymiarów.In other words, S and T have the same number of dimensions.
    • Zarówno SE, jak i TEreference_types.Both SE and TE are reference_types.
    • W SE do TEistnieje niejawna konwersja odwołania.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 dowolnych 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ę odniesienia do interfejsu lub typu delegata T0 a T0 jest konwersją 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_types, 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_types 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 napakowywania istnieje z dowolnego non_nullable_value_type do object i dynamic, do System.ValueType i do wszystkich INTERFACE_TYPE wdrożonych 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ę do interfejsu lub typu delegata I0, a 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ścią źródłową jest 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 opakowanej T wygenerowanej przez odpakowanie 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 do żądanego typu.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 używają niejawnych konwersji dynamicznych, 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ą poszukiwane z 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. Znaleziono konwersję do string ale nie 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, uintlub ulong, pod warunkiem, że wartość constant_expression należy do zakresu 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 ulongtypu, 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 swojej skutecznej klasy bazowej C, od T do dowolnej klasy bazowej Ci 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.
  • Od T do typu interfejsu I w Tobowiązującym interfejsie i od T do dowolnego interfejsu podstawowego 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.
  • Z T do Uparametru typu, udostępnione T zależy 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, wówczas T i U są takie same, 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 literału wartości null do Tdostarczone 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 a 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 konwersja 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ę do interfejsu lub typu delegata, I0 a I0 jest konwersją 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 znany jako 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.

Konwersje jawne, które nie są konwersjemi niejawnymi to konwersje, które nie mogą być sprawdzane w celu pomyślnego przeprowadzenia konwersji, które są znane do utraty informacji, a konwersje w różnych domenach typów są wystarczająco różne, aby oznaczać jawne służąc.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:

  • Z sbyte do byte, ushort, uint, ulonglub char.From sbyte to byte, ushort, uint, ulong, or char.
  • Z byte sbyte i char.From byte to sbyte and char.
  • Z short do sbyte, byte, ushort, uint, ulonglub char.From short to sbyte, byte, ushort, uint, ulong, or char.
  • Od ushort do sbyte, byte, shortlub char.From ushort to sbyte, byte, short, or char.
  • Z int do sbyte, byte, short, ushort, uint, ulonglub char.From int to sbyte, byte, short, ushort, uint, ulong, or char.
  • Z uint do sbyte, byte, short, ushort, intlub char.From uint to sbyte, byte, short, ushort, int, or char.
  • Z long do sbyte, byte, short, ushort, int, uint, ulonglub char.From long to sbyte, byte, short, ushort, int, uint, ulong, or char.
  • Z ulong do sbyte, byte, short, ushort, int, uint, longlub char.From ulong to sbyte, byte, short, ushort, int, uint, long, or char.
  • Od char do sbyte, bytelub short.From char to sbyte, byte, or short.
  • Z float do sbyte, byte, short, ushort, int, uint, long, ulong, charlub decimal.From float to sbyte, byte, short, ushort, int, uint, long, ulong, char, or decimal.
  • Z double do sbyte, byte, short, ushort, int, uint, long, ulong, char, floatlub decimal.From double to sbyte, byte, short, ushort, int, uint, long, ulong, char, float, or decimal.
  • Z decimal do sbyte, byte, short, ushort, int, uint, long, ulong, char, floatlub 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 kontekście checked konwersja kończy się powodzeniem, jeśli wartość operandu źródłowego należy do zakresu typu docelowego, ale zgłasza System.OverflowException, jeśli wartość operandu źródła jest spoza zakresu 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 kontekście unchecked 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 na typ całkowity, wartość źródłowa jest zaokrąglana do zera do najbliższej wartości całkowitej, a ta wartość całkowita będzie 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, zostanie zgłoszony System.OverflowException.If the resulting integral value is outside the range of the destination type, a System.OverflowException is thrown.
  • W przypadku konwersji z float lub double na typ całkowity, przetwarzanie zależy od kontekstu sprawdzania przepełnienia (Operatory sprawdzone i niezaznaczone), w których 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 kontekście checked 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, zostanie zgłoszony System.OverflowException.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 zostanie zgłoszony System.OverflowException.Otherwise, a System.OverflowException is thrown.
    • W kontekście unchecked 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.
  • W przypadku konwersji z double na floatwartość double jest zaokrąglana do najbliższej wartości float.For a conversion from double to float, the double value is rounded to the nearest float value. Jeśli wartość double jest zbyt mała, aby reprezentować ją 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 wartość double 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ścią 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 reprezentacja i zaokrąglana do najbliższej liczby po 28 miejsc 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, aby reprezentować ją 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, zostanie zgłoszony System.OverflowException.If the source value is NaN, infinity, or too large to represent as a decimal, a System.OverflowException is thrown.
  • W przypadku konwersji z decimal na float lub doublewartość decimal jest zaokrąglana do najbliższej wartości double lub float.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:

  • Z sbyte, byte, short, ushort, int, uint, long, ulong, char, float, doublelub decimal do dowolnej 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, doublelub 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 bazowym intkonwersja z E na byte jest przetwarzana jako jawna konwersja liczbowa (jawne konwersje liczbowe) od int do byte, a konwersja z byte do E jest przetwarzana jako niejawna konwersja liczbowa (niejawne konwersje liczbowe) od 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 na typ wartości niedopuszczających wartości null 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? na T?.An explicit conversion from S? to T?.
  • Jawna konwersja z S na T?.An explicit conversion from S to T?.
  • Jawna konwersja z S? na T.An explicit conversion from S? to T.

Obliczanie konwersji dopuszczającej wartość null na podstawie bazowej konwersji z S, aby T kontynuowały się 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ścią źródłową jest 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 po niej bazowa konwersja z S do T, po którym następuje Zawijanie z T 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 do wartości null jest z S do T?, konwersja jest szacowana jako bazowa konwersja z S do T, a po nim otoka z T 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 do wartości null jest z S? do T, konwersja jest oceniana jako odpakowanie od S? do S, a następnie 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:

  • Z object i dynamic do innych reference_type.From object and dynamic to any other reference_type.
  • Z dowolnego class_type S do dowolnego class_type T, podane S jest klasą bazową T.From any class_type S to any class_type T, provided S is a base class of T.
  • Z dowolnego class_type S do dowolnego INTERFACE_TYPE T, podane S nie jest zapieczętowane i podane S nie implementuje 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_type S do dowolnego class_type T, podane T nie jest zapieczętowane ani dostarczone T implementuje S.From any interface_type S to any class_type T, provided T is not sealed or provided T implements S.
  • Z dowolnego interface_type S do dowolnego INTERFACE_TYPE T, dostarczony S nie pochodzi od 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 T mają taką samą liczbę wymiarów.In other words, S and T have the same number of dimensions.
    • Zarówno SE, jak i TEreference_types.Both SE and TE are reference_types.
    • Istnieje jawna konwersja odwołań 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 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 explicit reference conversion from S to T.
  • Od 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 do typu referencyjnego T, jeśli ma on jawną konwersję referencyjną do typu referencyjnego T0 i T0 ma Tkonwersji tożsamości.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 typu delegata T, jeśli ma on jawną konwersję referencyjną do interfejsu lub typu delegata T0, a T0 jest konwersją wariancji do T lub T, można przekonwertować wariancję na 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ólnym typem delegata, D<S1...Sn> nie jest zgodny z lub identyczna z D<T1...Tn>, a dla każdego parametru typu Xi D: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, Si jest taka sama jak Ti.If Xi is invariant, then Si is identical to Ti.
    • Jeśli Xi jest współwariantem, 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, wówczas 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 źródła musi być nulllub rzeczywisty typ obiektu, do którego odwołuje się operand źródłowy, 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ę, zostanie zgłoszony System.InvalidCastException.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 wszelkich non_nullable_value_typeoraz od 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 a 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 ona konwersję rozpakowywania z interfejsu lub typu delegata, I0 a I0 jest konwersją wariancji do I lub I jest konwertowany na 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 w wyrażeniu typu dynamic do 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 będzie 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 do żądanego typu.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

Najlepszą konwersją o na C można znaleźć w czasie kompilacji jako jawną konwersję odwołań.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 d na C jednak jako jawna konwersja dynamiczna jest zawieszona do czasu wykonywania, w której zdefiniowana przez użytkownika konwersja z typu czasu wykonywania 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 efektywnej klasy bazowej C T do T oraz 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 wszelkich interface_type I z zastrzeżeniem, że nie istnieje jeszcze niejawna konwersja z T na 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, podane T zależy 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, wówczas T i U są takie same, 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 klasyfikowane 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 znany jako typ referencyjny, konwersje powyżej 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 
    }
}

Jeśli dozwolone jest bezpośrednie przekonwertowanie t na int, jeden z nich może ł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) następnie zgłosi wyjątek w czasie wykonywania, ponieważ int opakowane nie mogą być konwertowane 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 istnieje standardowa niejawna konwersja z typu A do typu B, wówczas istnieje standardowa jawna konwersja z typu A, aby wpisać B i z 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

C#zezwala na rozszerzanie wstępnie zdefiniowanych niejawnych i jawnych konwersji 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

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 są typami dopuszczających wartości null, pozwól S0 i T0 odnoszą 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 może deklarować konwersję z typu źródłowego S do typu docelowego 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.
  • S0 lub 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 ani T0 jest interface_typeem.Neither S0 nor T0 is an interface_type.
  • Oprócz konwersji zdefiniowanych przez użytkownika konwersja nie istnieje z S do T lub 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 typ wartości niedopuszczający wartości null S na typ wartości niedopuszczający wartości null T, istnieje zniesiony Operator konwersji , który konwertuje z S? na 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 podnieśny Operator konwersji wykonuje odpakowanie od S? do S, a po nim konwersja zdefiniowana przez użytkownika z S na T, a następnie otokę z T do T?, z tą różnicą, że S? wartość null jest konwertowana bezpośrednio na T?ową wartość null.This lifted conversion operator performs an unwrapping from S? to S followed by the user-defined conversion from S to T followed by a wrapping from T to T?, except that a null valued S? converts directly to a null valued T?.

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, nazywaną typem źródła, na inny typ o nazwie Typ docelowy.A user-defined conversion converts a value from its type, called the source type, to another type, called the target type. Ocena zdefiniowanych przez użytkownika centrów konwersji na potrzeby znajdowania 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. Inaczej mówiąc, konwersja z typu S do typu T nigdy nie wykona najpierw konwersji zdefiniowanej przez użytkownika z S na X, a następnie wykonaj 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 (niejawne konwersje) istnieje z typu A do typu B, a jeśli nie A ani BINTERFACE_TYPEs, wówczas A jest określana przez B, a 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_types, 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 mają Typy dopuszczające wartość null, S0 i T0 są ich typami podstawowymi, w przeciwnym razie S0 i T0 są równe odpowiednio S i T.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órych będą rozpatrywane 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ą), klasy bazowe 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, które konwertują z typu obejmującego S do typu, który obejmuje 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 podczas kompilowania.If U is empty, the conversion is undefined and a compile-time error occurs.
  • Znajdź najbardziej konkretny typ źródła, SXw Uoperatory:Find the most specific source type, SX, of the operators in U:
    • Jeśli którykolwiek z operatorów w U skonwertować z S, SX S.If any of the operators in U convert from S, then SX is S.
    • W przeciwnym razie SX jest najbardziej powiązanego typu 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, TXw Uoperatory:Find the most specific target type, TX, of the operators in U:
    • Jeśli którykolwiek z operatorów w U skonwertować na T, TX T.If any of the operators in U convert to T, then TX is T.
    • W przeciwnym razie TX 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, to 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, to jest to najbardziej konkretny 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 mają Typy dopuszczające wartość null, S0 i T0 są ich typami podstawowymi, w przeciwnym razie S0 i T0 są równe odpowiednio S i T.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órych będą rozpatrywane 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ą), klasy bazowe S0 (jeśli S0 jest klasą), T0 (jeśli T0 jest klasą lub strukturą), a klasy bazowe 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, które konwertują z typu obejmującego lub ponoszące S do typu, który obejmuje lub podano przez 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 podczas kompilowania.If U is empty, the conversion is undefined and a compile-time error occurs.
  • Znajdź najbardziej konkretny typ źródła, SXw Uoperatory:Find the most specific source type, SX, of the operators in U:
    • Jeśli którykolwiek z operatorów w U skonwertować z S, 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 konwertować z typów, które obejmują S, SX jest najbardziej połączoną 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 to najbardziej obejmujący typ w połączonym zestawie typów źródłowych 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, TXw Uoperatory:Find the most specific target type, TX, of the operators in U:
    • Jeśli którykolwiek z operatorów w U skonwertować na T, 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 skonwertować na typy, które są objęte T, wówczas 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 najbardziej powiązanego typu 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, to 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, to jest to najbardziej konkretny 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 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 na TX.The most specific user-defined conversion operator is invoked to convert from SX to TX.
    • Jeśli TX nie jest T, zostanie przeprowadzona 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 typem delegata D udostępnionym:Specifically, an anonymous function F is compatible with a delegate type D provided:

  • Jeśli F zawiera anonymous_function_signature, D i F mają taką samą liczbę parametrów.If F contains an anonymous_function_signature, then D and F have the same number of parameters.
  • Jeśli F nie zawiera anonymous_function_signature, D mogą mieć zero lub więcej parametrów dowolnego typu, o ile żaden parametr elementu D ma modyfikator parametru out.If F does not contain an anonymous_function_signature, then D may have zero or more parameters of any type, as long as no parameter of D has the out parameter modifier.
  • 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 zawiera niejawnie wpisaną listę parametrów, D nie ma ref lub out parametrów.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 typem zwracanym lub F jest Async i D ma typ zwracany Task, wtedy gdy każdy parametr z F ma 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, a D ma void typem zwracanym lub F jest Async, a D ma zwracany typ Task, wtedy gdy każdy parametr z F ma typ odpowiadającego parametru w D, treść F jest prawidłowym blokiem instrukcji (WRT Blocks), w którym żadna instrukcja return 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 F jest nieasynchroniczna i D ma typ zwracany inny niż void Tlub F jest Async i D ma typ zwracany Task<T>, wtedy gdy każdy parametr z F ma typ odpowiadającego parametru w D, treść F jest prawidłowym wyrażeniem (WRTExpressions), 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 blokiem instrukcji, a F nie jest Async i D ma typ zwracany inny niż void T, lub F jest Async i D ma typ zwracany Task<T>, a następnie, gdy każdy parametr F ma 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 instrukcja return 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 jest określony 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 jest błędem 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 wyniku 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ść elementu członkowskiego otaczającej 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 warunkach innych C# konstrukcji.This section describes a possible implementation of anonymous function conversions in terms of other C# constructs. Opisana tutaj implementacja opiera się na tych samych zasadach, które są używane przez C# kompilator firmy Microsoft, ale nie oznacza to, że jest to dozwolone wdrożenie, ani nie jest jedynym możliwym z nich.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 C# tylko innych konstrukcji.For each example, a corresponding translation to code that uses only other C# constructs is provided. W przykładach identyfikator D jest uznawany za reprezentujący 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 a także 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, Klasa wygenerowana 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, Klasa wygenerowana przez kompilator dla bloku instrukcji zewnętrznych, zawiera zmienną lokalną y i pole, które odwołuje się do this 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 dotarcie do 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ć reprezentowane jako dostęp do pól dla 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. Uwzględniając typ delegata D i wyrażenie E, które jest sklasyfikowane jako grupa metod, niejawna konwersja istnieje z E do D, jeśli E zawiera co najmniej jedną metodę, która jest stosowana w jej normalnej formie (odpowiedni element członkowski funkcji) do listy argumentów skonstruowanej przy użyciu 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 została opisana w poniższej.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 na D nie gwarantuje, że konwersja aplikacji w czasie kompilacji 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.

  • Wybrano jedną metodę M odpowiadającą wywołaniu metody (wywołania metody) E(A)formularza, 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) odpowiedniego 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 ma taką samą liczbę parametrów jak D, a 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 Dlub 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 F grupy metod 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żna utworzyć delegata do 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 taka konwersja nie istnieje, 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 obiekt docelowy jest null, zostanie zgłoszony System.NullReferenceException 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 obiekt docelowy 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, zostanie zgłoszony System.OutOfMemoryException 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.