Заглавная страница Избранные статьи Случайная статья Познавательные статьи Новые добавления Обратная связь FAQ Написать работу КАТЕГОРИИ: АрхеологияБиология Генетика География Информатика История Логика Маркетинг Математика Менеджмент Механика Педагогика Религия Социология Технологии Физика Философия Финансы Химия Экология ТОП 10 на сайте Приготовление дезинфицирующих растворов различной концентрацииТехника нижней прямой подачи мяча. Франко-прусская война (причины и последствия) Организация работы процедурного кабинета Смысловое и механическое запоминание, их место и роль в усвоении знаний Коммуникативные барьеры и пути их преодоления Обработка изделий медицинского назначения многократного применения Образцы текста публицистического стиля Четыре типа изменения баланса Задачи с ответами для Всероссийской олимпиады по праву Мы поможем в написании ваших работ! ЗНАЕТЕ ЛИ ВЫ?
Влияние общества на человека
Приготовление дезинфицирующих растворов различной концентрации Практические работы по географии для 6 класса Организация работы процедурного кабинета Изменения в неживой природе осенью Уборка процедурного кабинета Сольфеджио. Все правила по сольфеджио Балочные системы. Определение реакций опор и моментов защемления |
Variant type parameter listsСодержание книги
Поиск на нашем сайте
Variant type parameter lists can only occur on interface and delegate types. The difference from ordinary type-parameter-lists is the optional variance-annotation on each type parameter. variant-type-parameter-list: variant-type-parameters: variance-annotation: If the variance annotation is out, the type parameter is said to be covariant. If the variance annotation is in, the type parameter is said to be contravariant. If there is no variance annotation, the type parameter is said to be invariant. In the example interface C<out X, in Y, Z> Z P { get; set; } X is covariant, Y is contravariant and Z is invariant. Variance safety The occurrence of variance annotations in the type parameter list of a type restricts the places where types can occur within the type declaration. A type T is output-unsafe if one of the following holds: · T is a contravariant type parameter · T is an array type with an output-unsafe element type · T is an interface or delegate type S<A1,… AK> constructed from a generic type S<X1,.. XK> where for at least one Ai one of the following holds: o Xi is covariant or invariant and Ai is output-unsafe. o Xi is contravariant or invariant and Ai is input-safe. A type T is input-unsafe if one of the following holds: · T is a covariant type parameter · T is an array type with an input-unsafe element type · T is an interface or delegate type S<A1,… AK> constructed from a generic type S<X1,.. XK> where for at least one Ai one of the following holds: o Xi is covariant or invariant and Ai is input-unsafe. o Xi is contravariant or invariant and Ai is output-unsafe. Intuitively, an output-unsafe type is prohibited in an output position, and an input-unsafe type is prohibited in an input position. A type is output-safe if it is not output-unsafe, and input-safe if it is not input-unsafe. Variance conversion The purpose of variance annotations is to provide for more lenient (but still type safe) conversions to interface and delegate types. To this end the definitions of implicit (§6.1) and explicit conversions (§6.2) make use of the notion of variance-convertibility, which is defined as follows: A type T<A1, …, An> is variance-convertible to a type T<B1, …, Bn> if T is either an interface or a delegate type declared with the variant type parameters T<X1, …, Xn>, and for each variant type parameter Xi one of the following holds: · Xi is covariant and an implicit reference or identity conversion exists from Ai to Bi · Xi is contravariant and an implicit reference or identity conversion exists from Bi to Ai · Xi is invariant and an identity conversion exists from Ai to Bi Base interfaces An interface can inherit from zero or more interface types, which are called the explicit base interfaces of the interface. When an interface has one or more explicit base interfaces, then in the declaration of that interface, the interface identifier is followed by a colon and a comma separated list of base interface types. interface-base: For a constructed interface type, the explicit base interfaces are formed by taking the explicit base interface declarations on the generic type declaration, and substituting, for each type-parameter in the base interface declaration, the corresponding type-argument of the constructed type. The explicit base interfaces of an interface must be at least as accessible as the interface itself (§3.5.4). For example, it is a compile-time error to specify a private or internal interface in the interface-base of a public interface. It is a compile-time error for an interface to directly or indirectly inherit from itself. The base interfaces of an interface are the explicit base interfaces and their base interfaces. In other words, the set of base interfaces is the complete transitive closure of the explicit base interfaces, their explicit base interfaces, and so on. An interface inherits all members of its base interfaces. In the example interface IControl interface ITextBox: IControl interface IListBox: IControl interface IComboBox: ITextBox, IListBox {} the base interfaces of IComboBox are IControl, ITextBox, and IListBox. In other words, the IComboBox interface above inherits members SetText and SetItems as well as Paint. Every base interface of an interface must be output-safe (§13.1.3.1). A class or struct that implements an interface also implicitly implements all of the interface’s base interfaces. Interface body The interface-body of an interface defines the members of the interface. interface-body: Interface members The members of an interface are the members inherited from the base interfaces and the members declared by the interface itself. interface-member-declarations: interface-member-declaration: An interface declaration may declare zero or more members. The members of an interface must be methods, properties, events, or indexers. An interface cannot contain constants, fields, operators, instance constructors, destructors, or types, nor can an interface contain static members of any kind. All interface members implicitly have public access. It is a compile-time error for interface member declarations to include any modifiers. In particular, interfaces members cannot be declared with the modifiers abstract, public, protected, internal, private, virtual, override, or static. The example public delegate void StringListEvent(IStringList sender); public interface IStringList int Count { get; } event StringListEvent Changed; string this[int index] { get; set; } declares an interface that contains one each of the possible kinds of members: A method, a property, an event, and an indexer. An interface-declaration creates a new declaration space (§3.3), and the interface-member-declarations immediately contained by the interface-declaration introduce new members into this declaration space. The following rules apply to interface-member-declarations: · The name of a method must differ from the names of all properties and events declared in the same interface. In addition, the signature (§3.6) of a method must differ from the signatures of all other methods declared in the same interface, and two methods declared in the same interface may not have signatures that differ solely by ref and out. · The name of a property or event must differ from the names of all other members declared in the same interface. · The signature of an indexer must differ from the signatures of all other indexers declared in the same interface. The inherited members of an interface are specifically not part of the declaration space of the interface. Thus, an interface is allowed to declare a member with the same name or signature as an inherited member. When this occurs, the derived interface member is said to hide the base interface member. Hiding an inherited member is not considered an error, but it does cause the compiler to issue a warning. To suppress the warning, the declaration of the derived interface member must include a new modifier to indicate that the derived member is intended to hide the base member. This topic is discussed further in §3.7.1.2. If a new modifier is included in a declaration that doesn’t hide an inherited member, a warning is issued to that effect. This warning is suppressed by removing the new modifier. Note that the members in class object are not, strictly speaking, members of any interface (§13.2). However, the members in class object are available via member lookup in any interface type (§7.4). Interface methods Interface methods are declared using interface-method-declarations: interface-method-declaration: The attributes, return-type, identifier, and formal-parameter-list of an interface method declaration have the same meaning as those of a method declaration in a class (§10.6). An interface method declaration is not permitted to specify a method body, and the declaration therefore always ends with a semicolon. Each formal parameter type of an interface method must be input-safe (§13.1.3.1), and the return type must be either void or output-safe. Furthermore, each class type constraint, interface type constraint and type parameter constraint on any type parameter of the method must be input-safe. These rules ensure that any covariant or contravariant usage of the interface remains typesafe. For example, interface I<out T> { void M<U>() where U: T; } is illegal because the usage of T as a type parameter constraint on U is not input-safe. Were this restriction not in place it would be possible to violate type safety in the following manner: class B {} This is actually a call to C.M<E>. But that call requires that E derive from D, so type safety would be violated here. Interface properties Interface properties are declared using interface-property-declarations: interface-property-declaration: interface-accessors: The attributes, type, and identifier of an interface property declaration have the same meaning as those of a property declaration in a class (§10.7). The accessors of an interface property declaration correspond to the accessors of a class property declaration (§10.7.2), except that the accessor body must always be a semicolon. Thus, the accessors simply indicate whether the property is read-write, read-only, or write-only. The type of an interface property must be output-safe if there is a get accessor, and must be input-safe if there is a set accessor. Interface events Interface events are declared using interface-event-declarations: interface-event-declaration: The attributes, type, and identifier of an interface event declaration have the same meaning as those of an event declaration in a class (§10.8). The type of an interface event must be input-safe. Interface indexers Interface indexers are declared using interface-indexer-declarations: interface-indexer-declaration: The attributes, type, and formal-parameter-list of an interface indexer declaration have the same meaning as those of an indexer declaration in a class (§10.9). The accessors of an interface indexer declaration correspond to the accessors of a class indexer declaration (§10.9), except that the accessor body must always be a semicolon. Thus, the accessors simply indicate whether the indexer is read-write, read-only, or write-only. All the formal parameter types of an interface indexer must be input-safe. In addition, any out or ref formal parameter types must also be output-safe. Note that even out parameters are required to be input-safe, due to a limitiation of the underlying execution platform. The type of an interface indexer must be output-safe if there is a get accessor, and must be input-safe if there is a set accessor. Interface member access Interface members are accessed through member access (§7.6.4) and indexer access (§7.6.6.2) expressions of the form I.M and I[A], where I is an interface type, M is a method, property, or event of that interface type, and A is an indexer argument list. For interfaces that are strictly single-inheritance (each interface in the inheritance chain has exactly zero or one direct base interface), the effects of the member lookup (§7.4), method invocation (§7.6.5.1), and indexer access (§7.6.6.2) rules are exactly the same as for classes and structs: More derived members hide less derived members with the same name or signature. However, for multiple-inheritance interfaces, ambiguities can occur when two or more unrelated base interfaces declare members with the same name or signature. This section shows several examples of such situations. In all cases, explicit casts can be used to resolve the ambiguities. In the example interface IList interface ICounter interface IListCounter: IList, ICounter {} class C the first two statements cause compile-time errors because the member lookup (§7.4) of Count in IListCounter is ambiguous. As illustrated by the example, the ambiguity is resolved by casting x to the appropriate base interface type. Such casts have no run-time costs—they merely consist of viewing the instance as a less derived type at compile-time. In the example interface IInteger interface IDouble interface INumber: IInteger, IDouble {} class C the invocation n.Add(1) selects IInteger.Add by applying the overload resolution rules of §7.5.3. Similarly the invocation n.Add(1.0) selects IDouble.Add. When explicit casts are inserted, there is only one candidate method, and thus no ambiguity. In the example interface IBase interface ILeft: IBase interface IRight: IBase interface IDerived: ILeft, IRight {} class A the IBase.F member is hidden by the ILeft.F member. The invocation d.F(1) thus selects ILeft.F, even though IBase.F appears to not be hidden in the access path that leads through IRight. The intuitive rule for hiding in multiple-inheritance interfaces is simply this: If a member is hidden in any access path, it is hidden in all access paths. Because the access path from IDerived to ILeft to IBase hides IBase.F, the member is also hidden in the access path from IDerived to IRight to IBase.
|
||||
Последнее изменение этой страницы: 2016-08-10; просмотров: 291; Нарушение авторского права страницы; Мы поможем в написании вашей работы! infopedia.su Все материалы представленные на сайте исключительно с целью ознакомления читателями и не преследуют коммерческих целей или нарушение авторских прав. Обратная связь - 18.191.178.16 (0.006 с.) |