Студопедия — Type parameter constraints
Студопедия Главная Случайная страница Обратная связь

Разделы: Автомобили Астрономия Биология География Дом и сад Другие языки Другое Информатика История Культура Литература Логика Математика Медицина Металлургия Механика Образование Охрана труда Педагогика Политика Право Психология Религия Риторика Социология Спорт Строительство Технология Туризм Физика Философия Финансы Химия Черчение Экология Экономика Электроника

Type parameter constraints






Generic type and method declarations can optionally specify type parameter constraints by including type-parameter-constraints-clauses.

type-parameter-constraints-clauses:
type-parameter-constraints-clause
type-parameter-constraints-clauses type-parameter-constraints-clause

type-parameter-constraints-clause:
where type-parameter: type-parameter-constraints

type-parameter-constraints:
primary-constraint
secondary-constraints
constructor-constraint
primary-constraint, secondary-constraints
primary-constraint, constructor-constraint
secondary-constraints, constructor-constraint
primary-constraint, secondary-constraints, constructor-constraint

primary-constraint:
class-type
class
struct

secondary-constraints:
interface-type
type-parameter
secondary-constraints, interface-type
secondary-constraints, type-parameter

constructor-constraint:
new ()

Each type-parameter-constraints-clause consists of the token where, followed by the name of a type parameter, followed by a colon and the list of constraints for that type parameter. There can be at most one where clause for each type parameter, and the where clauses can be listed in any order. Like the get and set tokens in a property accessor, the where token is not a keyword.

The list of constraints given in a where clause can include any of the following components, in this order: a single primary constraint, one or more secondary constraints, and the constructor constraint, new().

A primary constraint can be a class type or the reference type constraint class or the value type constraint struct. A secondary constraint can be a type-parameter or interface-type.

The reference type constraint specifies that a type argument used for the type parameter must be a reference type. All class types, interface types, delegate types, array types, and type parameters known to be a reference type (as defined below) satisfy this constraint.

The value type constraint specifies that a type argument used for the type parameter must be a non-nullable value type. All non-nullable struct types, enum types, and type parameters having the value type constraint satisfy this constraint. Note that although classified as a value type, a nullable type (§4.1.10) does not satisfy the value type constraint. A type parameter having the value type constraint cannot also have the constructor-constraint.

Pointer types are never allowed to be type arguments and are not considered to satisfy either the reference type or value type constraints.

If a constraint is a class type, an interface type, or a type parameter, that type specifies a minimal “base type” that every type argument used for that type parameter must support. Whenever a constructed type or generic method is used, the type argument is checked against the constraints on the type parameter at compile-time. The type argument supplied must satisfy the conditions described in section 4.4.4.

A class-type constraint must satisfy the following rules:

· The type must be a class type.

· The type must not be sealed.

· The type must not be one of the following types: System.Array, System.Delegate, System.Enum, or System.ValueType.

· The type must not be object. Because all types derive from object, such a constraint would have no effect if it were permitted.

· At most one constraint for a given type parameter can be a class type.

A type specified as an interface-type constraint must satisfy the following rules:

· The type must be an interface type.

· A type must not be specified more than once in a given where clause.

In either case, the constraint can involve any of the type parameters of the associated type or method declaration as part of a constructed type, and can involve the type being declared.

Any class or interface type specified as a type parameter constraint must be at least as accessible (§3.5.4) as the generic type or method being declared.

A type specified as a type-parameter constraint must satisfy the following rules:

· The type must be a type parameter.

· A type must not be specified more than once in a given where clause.

In addition there must be no cycles in the dependency graph of type parameters, where dependency is a transitive relation defined by:

· If a type parameter T is used as a constraint for type parameter S then S depends on T.

· If a type parameter S depends on a type parameter T and T depends on a type parameter U then S depends on U.

Given this relation, it is a compile-time error for a type parameter to depend on itself (directly or indirectly).

Any constraints must be consistent among dependent type parameters. If type parameter S depends on type parameter T then:

· T must not have the value type constraint. Otherwise, T is effectively sealed so S would be forced to be the same type as T, eliminating the need for two type parameters.

· If S has the value type constraint then T must not have a class-type constraint.

· If S has a class-type constraint A and T has a class-type constraint B then there must be an identity conversion or implicit reference conversion from A to B or an implicit reference conversion from B to A.

· If S also depends on type parameter U and U has a class-type constraint A and T has a class-type constraint B then there must be an identity conversion or implicit reference conversion from A to B or an implicit reference conversion from B to A.

It is valid for S to have the value type constraint and T to have the reference type constraint. Effectively this limits T to the types System.Object, System.ValueType, System.Enum, and any interface type.

If the where clause for a type parameter includes a constructor constraint (which has the form new()), it is possible to use the new operator to create instances of the type (§7.6.10.1). Any type argument used for a type parameter with a constructor constraint must have a public parameterless constructor (this constructor implicitly exists for any value type) or be a type parameter having the value type constraint or constructor constraint (see §10.1.5 for details).

The following are examples of constraints:

interface IPrintable
{
void Print();
}

interface IComparable<T>
{
int CompareTo(T value);
}

interface IKeyProvider<T>
{

T GetKey();
}

class Printer<T> where T: IPrintable {...}

class SortedList<T> where T: IComparable<T> {...}

class Dictionary<K,V>
where K: IComparable<K>
where V: IPrintable, IKeyProvider<K>, new()
{
...
}

The following example is in error because it causes a circularity in the dependency graph of the type parameters:

class Circular<S,T>
where S: T
where T: S // Error, circularity in dependency graph
{
...
}

The following examples illustrate additional invalid situations:

class Sealed<S,T>
where S: T
where T: struct // Error, T is sealed
{
...
}

class A {...}

class B {...}

class Incompat<S,T>
where S: A, T
where T: B // Error, incompatible class-type constraints
{
...
}

class StructWithClass<S,T,U>
where S: struct, T
where T: U
where U: A // Error, A incompatible with struct
{
...
}

The effective base class of a type parameter T is defined as follows:

· If T has no primary constraints or type parameter constraints, its effective base class is object.

· If T has the value type constraint, its effective base class is System.ValueType.

· If T has a class-type constraint C but no type-parameter constraints, its effective base class is C.

· If T has no class-type constraint but has one or more type-parameter constraints, its effective base class is the most encompassed type (§6.4.2) in the set of effective base classes of its type-parameter constraints. The consistency rules ensure that such a most encompassed type exists.

· If T has both a class-type constraint and one or more type-parameter constraints, its effective base class is the most encompassed type (§6.4.2) in the set consisting of the class-type constraint of T and the effective base classes of its type-parameter constraints. The consistency rules ensure that such a most encompassed type exists.

· If T has the reference type constraint but no class-type constraints, its effective base class is object.

For the purpose of these rules, if T has a constraint V that is a value-type, use instead the most specific base type of V that is a class-type. This can never happen in an explicitly given constraint, but may occur when the constraints of a generic method are implicitly inherited by an overriding method declaration or an explicit implementation of an interface method.

These rules ensure that the effective base class is always a class-type.

The effective interface set of a type parameter T is defined as follows:

· If T has no secondary-constraints, its effective interface set is empty.

· If T has interface-type constraints but no type-parameter constraints, its effective interface set is its set of interface-type constraints.

· If T has no interface-type constraints but has type-parameter constraints, its effective interface set is the union of the effective interface sets of its type-parameter constraints.

· If T has both interface-type constraints and type-parameter constraints, its effective interface set is the union of its set of interface-type constraints and the effective interface sets of its type-parameter constraints.

A type parameter is known to be a reference type if it has the reference type constraint or its effective base class is not object or System.ValueType.

Values of a constrained type parameter type can be used to access the instance members implied by the constraints. In the example

interface IPrintable
{
void Print();
}

class Printer<T> where T: IPrintable
{
void PrintOne(T x) {
x.Print();
}
}

the methods of IPrintable can be invoked directly on x because T is constrained to always implement IPrintable.







Дата добавления: 2015-09-07; просмотров: 443. Нарушение авторских прав; Мы поможем в написании вашей работы!



Расчетные и графические задания Равновесный объем - это объем, определяемый равенством спроса и предложения...

Кардиналистский и ординалистский подходы Кардиналистский (количественный подход) к анализу полезности основан на представлении о возможности измерения различных благ в условных единицах полезности...

Обзор компонентов Multisim Компоненты – это основа любой схемы, это все элементы, из которых она состоит. Multisim оперирует с двумя категориями...

Композиция из абстрактных геометрических фигур Данная композиция состоит из линий, штриховки, абстрактных геометрических форм...

Меры безопасности при обращении с оружием и боеприпасами 64. Получение (сдача) оружия и боеприпасов для проведения стрельб осуществляется в установленном порядке[1]. 65. Безопасность при проведении стрельб обеспечивается...

Весы настольные циферблатные Весы настольные циферблатные РН-10Ц13 (рис.3.1) выпускаются с наибольшими пределами взвешивания 2...

Хронометражно-табличная методика определения суточного расхода энергии студента Цель: познакомиться с хронометражно-табличным методом опреде­ления суточного расхода энергии...

ОСНОВНЫЕ ТИПЫ МОЗГА ПОЗВОНОЧНЫХ Ихтиопсидный тип мозга характерен для низших позвоночных - рыб и амфибий...

Принципы, критерии и методы оценки и аттестации персонала   Аттестация персонала является одной их важнейших функций управления персоналом...

Пункты решения командира взвода на организацию боя. уяснение полученной задачи; оценка обстановки; принятие решения; проведение рекогносцировки; отдача боевого приказа; организация взаимодействия...

Studopedia.info - Студопедия - 2014-2024 год . (0.008 сек.) русская версия | украинская версия