Maison  >  Article  >  développement back-end  >  Spécification C# 2.0 (Génériques 6)

Spécification C# 2.0 (Génériques 6)

黄舟
黄舟original
2017-01-03 10:44:171144parcourir

Connecté aux génériques 5

20.8 Expressions et instructions

Les opérations de certaines expressions et instructions ont été modifiées pour les génériques. Cette section décrit ces changements.

20.8.1 Expressions de valeur par défaut

Les expressions de valeur par défaut sont utilisées pour obtenir la valeur par défaut d'un type (§5.2). Habituellement, une expression de valeur par défaut est utilisée pour les paramètres de type, car si le paramètre de type est un type valeur ou un type référence, il se peut qu'il ne soit pas déjà là. (Il n'y a pas de conversion du type nul en paramètre de type.)

primary-no-array-creation-expression:(基本无数组创建表达式:)
…
default-value-expression(默认值表达式)
default-value-expression:(默认值表达式:) 
primary-expression . default (基本表达式 .default)
predefined-type . default(预定义类型. default)

Si une expression de base est utilisée dans une expression de valeur par défaut et que l'expression de base ne peut pas être divisée en un type, alors un une erreur de compilation se produira. Cependant les règles décrites au §7.5.4.1 s'appliquent également aux composants formant E.default.
Si le côté gauche de l'expression de valeur par défaut est évalué au moment de l'exécution par rapport à un type de référence, le résultat est converti en null vers ce type. Si le côté gauche d'une expression de valeur par défaut est évalué au moment de l'exécution par rapport à un type valeur, le résultat est la valeur par défaut du type valeur (§4.1.2).
Si le type est un type de référence ou un paramètre de type avec une contrainte de classe, l'expression de valeur par défaut est une expression constante (§7.15). De plus, l'expression de valeur par défaut est une expression constante si le type est l'un des suivants : sbyte, byte, short, ushort, int, uint, long, ulong, char, float, double, decimal ou bool.

20.8.2 Expressions de création d'objets

Le type d'expressions communes d'objets peut être un paramètre de type. Lorsqu'un paramètre de type est spécifié comme type dans une expression de création d'objet, les deux conditions suivantes doivent être remplies, sinon une erreur de compilation se produira

La liste de paramètres réelle doit être supprimée
Doit être spécifiée pour le paramètre de type Contraintes de constructeur de la forme new()

exécute une expression de création d'objet en créant une instance du type d'exécution auquel le paramètre de type est lié et en appelant le constructeur par défaut de ce type. Les types d’exécution peuvent être des types référence ou valeur.

20.8.3 Types d'opérateurs

L'opérateur typeof peut être utilisé pour les paramètres de type. Le résultat est un objet System.Type du type d’exécution lié au paramètre type. L'opérateur typeof peut également être utilisé pour construire des types.

class X <T>
{
public static void PrintTypes()
{
Console.WriteLine(typeof(T).FullName);
Console.WriteLine(typeof(X<X<T>>).FullName);
}
}
class M
{
static void Main()
{
X<int>.PrintTypes();
}
}

Le programme précédent s'imprimera comme suit.

System.Int32
X<X<Sytem.Int32>>
Typeof运算符不能用于没有指定类型实参的泛型类型声明的名字。
class X<T>{…}
class M
{
static void Main()
{
Type t = typeof(X); //错误,X需要类型实参
}
}

20.8.4 Opérateur d'égalité de référence

Si T est contraint par une contrainte de classe, l'opérateur d'égalité de type référence peut être utilisé pour comparer les valeurs du type paramètre T.
L'utilisation de l'opérateur d'égalité de type de référence permet de comparer facilement les paramètres réels du paramètre de type T avec d'autres paramètres réels qui sont nuls, même si T n'a aucune contrainte de classe. Au moment de l'exécution, si T est un type valeur, le résultat de la comparaison sera faux.

L'exemple suivant vérifie si le paramètre réel d'un type de paramètre de type sans contrainte est nul.

class C<T>
{
void F(T x)
{
if(x==null) thow new ArgumentNullException();
…
}
}

Même si T peut représenter un type valeur, la construction x==null est autorisée, et lorsque T est un type valeur, son résultat est simplement défini comme faux.

20.8.5 is运算符

在开放类型上的is运算符操作遵循通常的规则(§7.9.9)。如果e或T的编译时类型是一个开放类型,那么在运行时对于e和T将总是执行动态类型检查。

20.8.6as运算符

只要T有一个类约束,类型参数T可被用在as运算符的右边。这种限制是需要的,因为值null可能被作为运算符的结果返回。

class X
{
public T F<T>(object o) where T:Attribute
{
return o as T; //ok,T有一个类约束
}
public T G<T>(object o)
{
return o as T; //错误,T没有约束
}

}
在as运算符(§7.9.10)的当前规范中,对于表达式e as T最后一点表明,如果从e的编译时类型到T,不存在有效的显式引用转换,将会出现编译时错误。对于泛型,这条规则稍微作了修改。如果E的编译时类型或T是一个开放类型,在这种情况下将不会出现编译时错误;相反,运行时检查将会执行。

20.8.7异常语句

对于开放类型,throw(§8.9.5)和try(§8.10)的通常规则是适用的。

只要类型参数具有System.Exeption异常(或子类具有)作为类约束,那么throw语句可以被用作其类型有一个类型参数给定的表达式。 
只要类型参数System.Exception(或子类子类具有)作为类约束,那么在catch语句中的命名的类型可能是一个类型参数。

20.8.8 lock语句

lock语句可以被用作其类型由一个类型参数给定的表达式。如果表达式的运行时类型是一个值类型,lock将没有效果(因为对于装箱值不能有任何其他的引用)。

20.8.9 using 语句

using 语句(§8.13)遵循通常的规则:表达式必须被隐式的转换到System.IDisposable。如果类型参数通过System.IDisposable而约束,那么该类型的表达式可以使用using 语句。

20.8.10 foreach语句

给定如下形式的foreach语句
foreach(ElementType element in collection) statement
如果集合表达式是一个没有实现集合模式的类型,但为每个类型T实现了构造接口System.Collections.Generic.IEnumerable8742468051c85b06f0a0af9e3e506b5c,那么foreach语句的扩展是

IEnumerator<T> enumerator = ((IEnuemrable<T>)(collection).GetEnumerator();
try
{
where (enumerator.MoveNext()){
ElementType element = (ElementType)enumerator.Current;
statement;
}
}
finally{
enumerator.Dispose();
}

20.9查找规则修订

泛型修改了用于查找和绑定名字的某些基本规则。下面几节在考虑泛型的情况下,重新叙述了所有的基本名字查找规则。

20.9.1命名空间和类型名字

Le contenu suivant peut remplacer le §3.8.
Il existe plusieurs contextes dans les programmes C# qui nécessitent de spécifier des espaces de noms ou des noms de types. Toute forme de nom peut être constituée d'un ou plusieurs identifiants séparés par des signes "."
nom de l'espace de noms : (nom de l'espace de noms :)
nom de l'espace de noms ou du type (nom de l'espace de noms ou du type)
nom du type : (nom du type :)
nom de l'espace de noms ou du type (espace de noms ou nom de type)
namespace-or-type-name : (espace de noms ou nom de type :)
identifiant type-argument-list opt ​​​​(identifiant type liste d'arguments facultatif)
namespace-or- type-name . identifier type-argument-list opt ​​​​(espace de noms ou nom de type. identifiant type argument list facultatif)
Le nom de l'espace de noms est le nom de l'espace de noms ou le nom du type qui fait référence à l'espace de noms ( namespace-or-type- nom). Consultez les décisions décrites ci-dessous. L'espace de noms ou le nom de type d'un nom d'espace de noms doit faire référence à un espace de noms, sinon une erreur de compilation se produit. Il ne peut pas y avoir d'arguments de type dans un nom d'espace de noms (seuls les types peuvent avoir des arguments de type).
Un nom de type est un nom d'espace de noms ou de type qui fait référence à un type. Consultez les décisions décrites ci-dessous. L'espace de noms ou le nom de type d'un nom de type doit faire référence à un type, sinon une erreur de compilation se produit.
La signification d'un espace de noms ou d'un nom de type est déterminée comme suit.

Si l'espace de noms ou le nom de type est de la forme I ou If53db7e3537772cbf9ba1634d2b17fe6, où I est un identifiant unique et f53db7e3537772cbf9ba1634d2b17fe6

- Si un espace de noms ou un nom de type apparaît dans une déclaration de méthode générique et que cette déclaration inclut un paramètre de type nommé par I sans liste d'arguments de type spécifiée, alors un espace de noms ou une référence de nom de type Le paramètre de type.
- Sinon, si un espace de noms ou un nom de type apparaît dans une déclaration de type, alors pour chaque instance de type T (f53db7e3537772cbf9ba1634d2b17fe620.1.2), en commençant par le type d'instance de cette déclaration de type, et continue avec chaque déclaration de type de classe ou de structure englobante (le cas échéant)
u Si aucune déclaration contenant un paramètre de type T contenant le nom donné par I n'est spécifiée et qu'il n'y a pas de liste d'arguments de type, alors l'espace de noms ou le nom de type Référence qui paramètre de type.


u Sinon, si I est le nom d'un membre accessible de T, et si ce membre est un type avec un nombre correspondant de paramètres de type, alors l'espace de noms ou le nom de type fait référence au type T.I ou tapez T .I0c4640bb3be93baace618a998f381d1c. Notez que lors de la détermination de la signification des noms d'espace de noms ou de type, les membres non typés (constantes, champs, méthodes, propriétés, indexeurs, opérateurs, constructeurs d'instances, destructeurs et constructeurs statiques) et ceux avec un nombre différent de paramètres de type seront ignorés.
- Sinon, pour chaque espace de noms N commençant par un espace de noms ou un nom de type qui y apparaît, et continuant avec chaque espace de noms englobant (le cas échéant), puis se terminant par l'espace de noms global, les étapes suivantes seront calculées jusqu'à ce que l'entité soit localisée .
u Si I est un nom dans un espace de noms dans N et qu'aucune liste d'arguments de type n'est spécifiée, alors l'espace de noms ou le nom de type fait référence à cet espace de noms.
u Sinon, si I est le nom d'un type accessible dans N avec un nombre correspondant d'arguments de type, alors l'espace de noms ou le nom de type fait référence à un type construit avec les arguments de type donnés.
u Sinon, si l'espace de noms ou le nom du type apparaît dans une position entourée d'une déclaration d'espace de noms de N
- si la déclaration d'espace de noms contient une directive using alias avec un nom donné par I, et que I a un espace de nom d'importation ou type, et qu'aucune liste d'arguments n'est spécifiée, alors l'espace de noms ou le nom de type fait référence à cet espace de noms ou type
- sinon, si l'espace de noms importé par la directive using namespace de la déclaration d'espace de noms contient un espace de noms avec A donné type nommé qui correspond au nombre de paramètres de type, alors l'espace de noms ou le nom de type fait référence au type construit à partir des arguments de type donnés.
- Sinon, si l'espace de noms importé par la directive using namespace dans la déclaration d'espace de noms contient plus d'un type avec le nom donné, correspondant au nombre d'arguments de type, alors l'espace de noms ou le nom du type est ambigu et entraînera un erreur.
- Sinon, l'espace de noms ou le nom du type n'est pas défini et une erreur de compilation se produit.


l Sinon, l'espace de noms ou le nom de type est de la forme N.I ou N.If53db7e3537772cbf9ba1634d2b17fe6, où N est un espace de noms ou un nom de type, I est un identifiant et < ;A1,…,AN> est une liste d’arguments de type facultatifs. N est d'abord déterminé comme un espace de noms ou un nom de type. Si la décision de N échoue, une erreur de compilation se produira. Sinon, N.I ou N.If53db7e3537772cbf9ba1634d2b17fe6 sera décidé comme suit.
- Si N fait référence à un espace de noms, et si I est un nom d'espace de noms intégré dans N et qu'aucune liste d'arguments de type n'est spécifiée, alors l'espace de noms ou le nom de type fait référence à l'espace de noms intégré.
- Sinon, si N fait référence à un espace de noms et que I est le nom d'un type accessible dans N avec un nombre correspondant d'arguments de type, alors l'espace de noms ou le nom de type fait référence au type construit à partir des arguments de type donnés.
- Sinon, si N fait référence à un type de classe ou de structure et que I est le nom d'un type accessible intégré dans N avec des paramètres de type correspondants, alors l'espace de noms ou la référence du nom de type est construit avec les arguments donnés pour ce type.
- Sinon, N.I est un nom d'espace de noms non valide et une erreur de compilation se produira.

20.9.2 Recherche de membres

Le contenu suivant peut être remplacé §7.3

La recherche de membres est un processus qui détermine le type en fonction de sa signification dans le contexte. Au sein d'une expression, la recherche de membre peut se produire sous la forme d'une simple évaluation de nom ou d'un accès membre (§20.9.4).
La recherche de membres de nom N en type T est déterminée selon les règles suivantes.

Tout d'abord, un ensemble de membres accessibles nommés N est déterminé.

- Si T est un paramètre de type, alors dans chaque type spécifié comme contrainte de classe ou contrainte d'interface de T, ainsi que l'ensemble des membres nommés de N dans l'objet, cet ensemble est nommé Membres d'accès de la fédération .
- Sinon, cet ensemble se compose de tous les membres accessibles nommés de N dans T, y compris les membres hérités et les membres accessibles nommés de N dans l'objet. Si T est un type construit, l'ensemble des membres est obtenu en remplaçant les arguments de type comme décrit au §20.5.4. Les membres incluant le modificateur de remplacement seront expulsés de la collection.




Les membres masqués par d'autres membres sont ensuite supprimés de l'ensemble. Pour chaque membre S.M d'un ensemble, où S est le type dans lequel M est déclaré, les règles suivantes s'appliquent

- Si M est une constante, un champ, une propriété, un événement ou un membre d'énumération, alors dans Tous les membres déclarés dans les classes de base de S seront supprimés de cette collection.
- Si M est une déclaration de type, alors toutes les déclarations non-type dans la classe de base de S sont supprimées de l'ensemble, et toutes les déclarations de type de M avec le même nombre de paramètres de type que S déclarées dans le type de base, sera retiré de la collection.
- Si M est une méthode, alors tous les membres non-méthodes déclarés dans la classe de base de S seront supprimés de cet ensemble, et toutes les méthodes avec la même signature de M déclarée dans le type de base que S seront supprimées de cette collection.

Ensuite, les membres de l'interface masqués via les membres de la classe sont supprimés de la collection. Cette étape n'est valide que lorsque T est un paramètre de type et que T a des contraintes de classe et plusieurs contraintes d'interface. Pour chaque membre S.M de la collection, où S est le type dans lequel M est déclaré, si S est une déclaration de classe plutôt qu'un objet, les règles suivantes s'appliquent

- si M est une constante, un champ, une propriété , événement, membre d'énumération ou déclaration de type, alors tous les membres déclarés dans la déclaration d'interface seront supprimés de cette collection.
- Si M est une méthode, alors tous les membres non-méthode déclarés dans le type d'interface seront supprimés de cet ensemble, et toutes les méthodes avec la même signature de M déclarée dans l'interface comme S seront supprimées de cet ensemble . Supprimé de cette collection.

Enfin, après avoir supprimé les membres masqués, le résultat de la recherche sera déterminé

- Si une collection est constituée d'un seul membre, pas d'un type ou d'une méthode, alors ce membre est le résultat de la recherche.
- Sinon, si l'ensemble ne contient que des méthodes, alors cet ensemble de méthodes est le résultat de la recherche.
- Sinon, si l'ensemble ne contient que des déclarations de type, alors cet ensemble de déclarations de type est dans le résultat de la recherche de membre.
- Sinon, la recherche est ambiguë et une erreur de compilation se produira.
Pour les types, plutôt que les paramètres de type et les recherches de membres des interfaces, les recherches de membres dans les interfaces sont strictement un héritage unique (chaque interface dans la chaîne d'héritage a exactement zéro ou une interface de base directe), recherche L'effet de la règle est seulement cela les membres dérivés masquent les membres de la classe de base portant le même nom et la même signature. Cette recherche d'héritage unique est très explicite. Des ambiguïtés possibles dans la recherche de membres proviennent de l'interface d'héritage multiple décrite au §13.2.5

20.9.3 Noms simples

Le contenu suivant peut remplacer le §7.5.2.
Un nom simple est constitué d'un identifiant, suivi d'une liste facultative de paramètres de type.
simple-name : (nom simple :)
identifiant type-argument-list opt ​​​​(identifiant type argument list facultatif)
Pour les noms simples de la forme I ou If53db7e3537772cbf9ba1634d2b17fe6 , où I est un identifiant et If53db7e3537772cbf9ba1634d2b17fe6 est une liste d'arguments de type facultatifs qui peuvent être calculés et classés comme suit.

Si le nom simple apparaît dans un bloc, et si l'espace de déclaration de variable locale du bloc contient une variable locale ou un paramètre avec le nom donné par I, alors le nom simple fait référence à la variable locale et au paramètre et agit comme une variable Et être classé. Si une liste d'arguments de type est spécifiée, une erreur de compilation se produira.
Si le nom simple apparaît dans le corps d'une déclaration de méthode générique et si cette déclaration contient un paramètre de type nommé par I, alors le nom simple fait référence à ce paramètre de type. Si seule la liste d'arguments de type est spécifiée, elle le sera. Une erreur de compilation s'est produite.
Sinon, pour chaque instance de type T qui commence par un type d'instance déclaré par la classe, la structure ou l'énumération directement englobante, continuez avec le type d'instance déclaré par chaque classe ou structure externe englobante, le cas échéant.

- Si la déclaration de T inclut un paramètre de type nommé par I, alors le nom simple fait référence à ce paramètre de type. Si une liste d'arguments de type est spécifiée, une erreur de compilation se produira.
- Sinon, si une recherche de membre de I dans T produit une correspondance
u Si T est un type d'instance d'une classe ou d'un type de structure directement englobant et que la recherche identifie une ou plusieurs méthodes, le résultat sera un match with Le groupe de méthodes associé à cette expression. Si une liste d'arguments de type est spécifiée, elle est utilisée dans un appel de méthode générique (§20.6.3).
u Si T est un type d'instance d'une classe ou d'un type de structure directement englobant, si la recherche identifie un membre d'instance et que la référence se produit dans un bloc d'un constructeur d'instance, d'une méthode d'instance ou d'un accesseur d'instance, le résultat sera de même que cet accès Membre du formulaire .I est similaire. Si un argument de type est spécifié, une erreur de compilation se produira.
u Sinon, le résultat est similaire à l'accès membre du formulaire T.I ou T.If53db7e3537772cbf9ba1634d2b17fe6. Dans ce cas, ce serait une erreur de compilation que de faire référence à un membre d'instance par son simple nom.


Sinon, pour l'espace de noms N avec chaque espace de noms dans lequel le nom simple apparaît, continuez avec chaque espace de noms englobant (le cas échéant), et terminez par l'espace de noms global, Les étapes suivantes seront calculées jusqu'à ce qu'une entité est situé.

- Si I est le nom d'un espace de noms dans N et qu'aucune liste d'arguments de type n'est spécifiée, alors le nom simple fera référence à cet espace de noms.
- Sinon, si I est le nom d'un type accessible dans N avec un nombre correspondant d'arguments de type, alors le type simple fait référence à ce type construit à partir des arguments de type donnés.
u Si la déclaration d'espace de noms contient une directive using alias associée à un nom donné par I, où I est un espace de noms ou un type importé, et qu'aucune liste d'arguments de type n'est spécifiée, alors le nom simple fait référence à l'espace de noms ou au type.
u Sinon, si l'espace de noms importé par la directive using namespace dans la déclaration d'espace de noms contient un type nommé par I qui correspond au nombre d'arguments de type, alors une simple référence de nom est construite à partir du type d'arguments de type donné.
u Sinon, si l'espace de noms importé par la directive using namespace de la déclaration d'espace de noms contient plusieurs types dont les noms donnés par I correspondent au nombre d'arguments de type, alors les noms simples sont ambigus et entraîneront une erreur de compilation.
l Sinon, le nom donné par le nom simple n'est pas défini et entraînera une erreur de compilation.

20.9.4 Accès membres

Le contenu suivant peut remplacer le §7.5.4.
L'accès membre consiste en une expression de base ou un type prédéfini, suivi d'une marque ".", suivi d'un identifiant, puis d'une liste facultative d'arguments de type.
accès membre : (accès membre :)
expression-primaire . identifiant type-argument-list opt ​​​​(expression de base. Liste d'arguments de type d'identifiant facultative)
type-prédéfini . list opt ​​​​(type prédéfini. Liste d'arguments de type d'identifiant facultatif) Type prédéfini : l'un des éléments suivants
bool byte char decimal double float int long
object sbyte short string uint ulong ushort

Pour membre accès de la forme E.I ou E.If53db7e3537772cbf9ba1634d2b17fe6, où E est une expression de base ou un type prédéfini, I est un identifiant et f53db7e3537772cbf9ba1634d2b17fe6 sera calculé et trié comme suit.

Si E est un espace de noms et I est le nom d'un espace de noms imbriqué dans E et qu'aucun argument de type n'est spécifié, alors le résultat est cet espace de noms.
Si E est un espace de noms, I est le nom d'un type accessible dans E et E correspond au nombre de paramètres de type, alors le résultat est le type construit à partir des arguments de type donnés.
Si E est un type prédéfini ou une expression de base classée comme type, si E n'est pas un paramètre de type et si une recherche de membre de I dans E donne une correspondance, alors E.I est évalué et classé comme suit.

- Si j'identifie une ou plusieurs déclarations de type, alors cette déclaration de type est déterminée en utilisant le même nombre d'arguments de type (éventuellement zéro) que si elle était fournie dans les arguments de type. Le résultat est un type construit à partir des arguments de type donnés. Si la déclaration de type ne correspond pas au nombre de paramètres de type, une erreur de compilation se produira.
- Si j'identifie une ou plusieurs méthodes, le résultat est un groupe de méthodes sans expression d'instance associée. Si une liste d'arguments de type est spécifiée, elle sera utilisée dans les appels de méthode génériques (§20.6.3).
- Si j'identifie une propriété statique, un champ statique, un événement statique, une constante ou un membre d'énumération, une erreur de compilation se produira si une liste d'arguments de type est spécifiée.
- Si j'identifie une propriété statique, le résultat est un accès à la propriété avec une expression d'instance non associée.
- Si j'identifie un champ statique
u Si le champ est en lecture seule et que la référence apparaît en dehors du constructeur statique de la classe ou de la structure, le champ sera déclaré ici. Le résultat est alors une valeur, qui est la valeur du champ statique I dans E.
u Sinon, le résultat est une variable, qui est le champ statique I dans E.
- Si I identifie un événement statique
u Si la référence apparaît dans la classe ou la structure dans laquelle l'événement est déclaré, et que l'événement est déclaré sans déclaration d'accesseur d'événement (§10.7), alors E.I est traité comme si j'étais un champ statique.
u Sinon, le résultat est un accès événementiel à une expression d'instance non associée.
- Si j'identifie une constante, alors le résultat est la valeur, qui est la valeur de la constante.

- Si j'identifie un membre de l'énumération, le résultat est une valeur, qui est la valeur du membre de l'énumération.
- Sinon, E.I est une référence de membre invalide et provoquera une erreur de compilation.


Si E est un accès à une propriété, un accès à un indexeur, une variable ou une valeur dont le type est T, et qu'une recherche de membre de I dans T produit une correspondance, alors E.I est calculé et classé comme suit.

- Premièrement, si E est une propriété ou un accès indexeur, alors la valeur de la propriété ou de l'accès indexeur est obtenue (§7.1.1), et E est reclassé en valeur.
- Si I identifie une ou plusieurs méthodes, le résultat est un groupe de méthodes avec une expression d'instance associée de E. Si une liste d'arguments de type est spécifiée, elle sera utilisée dans les appels de méthode génériques (§20.6.3).
- Si j'identifie une propriété d'instance, un champ d'instance ou un événement d'instance, une erreur de compilation sera générée si une liste d'arguments de type est spécifiée.
- Si I identifie une propriété d'instance, le résultat est une expression d'instance avec un E associé.
- Si T est un type de classe et I identifie un champ d'instance du type de classe
u Si la valeur de E est nulle, une System.NullReferenceException sera levée.
u Sinon, si le champ est en lecture seule et que la référence se produit en dehors d'un constructeur d'instance de la classe dans laquelle le champ est déclaré, alors le résultat est la valeur qui est la valeur de I dans l'objet référencé par E.
u Sinon, le résultat est la variable, qui est le champ I dans l'objet référencé par E.
- si T est un type struct et I identifie un champ d'instance de ce type de struct
u si E est une valeur, ou si le champ est en lecture seule et que la référence apparaît dans le constructeur d'instance de la struct dont le champ est déclaré autrement, le résultat est une valeur, c'est-à-dire la valeur du champ I dans l'instance de structure donnée par E.
u Sinon, le résultat est une variable, c'est-à-dire le champ I dans l'instance de la structure donnée par E
- si I identifie un événement d'instance
u si la référence apparaît dans la classe ou la structure ; dans lequel l'événement a été déclaré et l'événement est déclaré sans déclaration d'accesseur d'événement, alors E.I est traité comme si j'étais un champ d'instance.
u Sinon, le résultat est une expression d'instance avec un E associé.

Sinon, E.I est une référence de membre non valide et provoquera une erreur de compilation.

20.9.5 Appel de méthode

Le contenu suivant peut remplacer la partie de traitement au moment de la compilation décrivant l'appel de méthode au §7.5.5.1.
Traitement au moment de la compilation des appels de méthode sous la forme de M(A), où M est un groupe de méthodes (peut contenir une liste d'arguments de type), A est une liste d'arguments facultative, composée des étapes suivantes.

Un ensemble candidat d'appels de méthodes est construit. Pour chaque méthode F

associée au groupe de méthodes M - si F est non générique, F est candidate lorsque
u M n'a pas de liste d'arguments de type, et
u pour A (§7.4. 2.1), F est applicable.
- Si F est un générique et M n'a pas de liste d'arguments de type, F est un candidat quand , et
u Une fois que les arguments de type déduits remplacent les paramètres de type de méthode correspondants, la liste de paramètres de F est applicable à A, et
u Après avoir remplacé les arguments de type, la liste des paramètres de F est aussi applicable que possible. Les méthodes non génériques déclarées comme F dans le même type sont différentes dans leur forme étendue (§7.4.2.1).
- Si F est un générique et M inclut une liste d'arguments de type, F est un candidat lorsque les paramètres, et
u Une fois que les arguments de type remplacent les paramètres de type de méthode correspondants, la liste de paramètres de F est applicable à A ( §7.4.2.1).

L'ensemble des méthodes candidates est réduit pour contenir uniquement des méthodes dérivées de types profondément dérivés : pour chaque méthode C.F de l'ensemble, C est le type dans lequel F est déclaré, et le type de base de C est déclaré dans Toutes les méthodes sont supprimées de la collection.
Si l'ensemble de résultats de la méthode candidate est vide, alors aucune méthode applicable n'existe et une erreur de compilation se produira. Si la méthode candidate n'est pas déclarée dans le même type, l'appel de méthode sera ambigu et une erreur de compilation se produira (ce dernier cas n'est possible que pour une méthode dans une interface avec plusieurs interfaces de base directes), comme décrit dans §13.2.5).

La meilleure méthode parmi l'ensemble des méthodes candidates est identifiée à l'aide de la règle de décision de surcharge (§7.4.2). Si une seule meilleure méthode ne peut pas être identifiée, l’appel de méthode est ambigu et génère une erreur de compilation. Lors de l'exécution d'une résolution de surcharge, les paramètres d'une méthode générique sont pris en compte après avoir remplacé les paramètres de type de méthode correspondants par des arguments de type (fournis ou déduits).

La validation finale de la meilleure méthode choisie est effectuée


- La méthode est valide dans le contexte d'un groupe de méthodes : si la méthode est une méthode statique, le groupe de méthodes doit être dérivé du nom simple ou Accès membre. Si la meilleure méthode est une méthode d'instance, le groupe de méthodes doit être accessible via une variable, une valeur ou un accès à la base dérivé d'un simple nom ou d'un accès membre. Si aucune de ces conditions n’est remplie, une erreur de compilation se produira.
- Si la meilleure méthode est une méthode générique, les arguments de type (fournis ou déduits) seront vérifiés par rapport aux contraintes déclarées sur la méthode générique. Si un argument de type ne satisfait pas aux contraintes du paramètre de type correspondant, une erreur de compilation est générée.
Une fois la méthode sélectionnée et vérifiée selon les étapes précédentes, l'appel d'exécution réel sera traité conformément aux règles d'appel des membres de fonction du §7.4.

20.9.6 Expression de création de délégué

Le contenu suivant peut remplacer la partie traitement au moment de la compilation de l'expression de création de délégué au §7.5.10.3.
Le traitement au moment de la compilation des expressions de création de délégués sous la forme de new D(E), où D est un type de délégué et E est une expression, comprend les étapes suivantes.

Si E est un groupe de méthodes

- correspondant à un appel de méthode de la forme E(A), un seul appel de méthode sera sélectionné.
u Le type de paramètre et le modificateur (ref ou out) de D sont utilisés comme type d'argument et modificateur de la liste d'arguments A.
u Les conversions ne sont pas prises en compte dans les tests applicables et l'inférence de type. Dans les cas où la conversion implicite est suffisante, les exigences de type sont identiques.
u L'étape de décision de surcharge ne sera pas exécutée. Au lieu de cela, l'ensemble des candidats doit contenir exactement une méthode compatible D (en utilisant alors des arguments de type au lieu de paramètres de type), et cette méthode deviendra la méthode référencée par le délégué nouvellement créé. Si aucune méthode de correspondance n’existe ou s’il existe plusieurs méthodes de correspondance, une erreur de compilation se produit.


- Si la méthode sélectionnée est une méthode d'instance, l'expression d'instance associée à E détermine l'objet cible du délégué.
- Le résultat est une valeur de type D, qui fait référence à la méthode sélectionnée et au délégué nouvellement créé de l'objet cible.

Sinon, E est une valeur de type délégué

- D et E doivent être compatibles sinon une erreur de compilation se produit.
- Le résultat est une valeur de type D, c'est à dire un délégué nouvellement créé référençant la même liste d'appels que E.

Sinon, l'expression de création du délégué n'est pas valide et une erreur de compilation se produit.

20.10 Modifications de la syntaxe du décalage vers la droite

Les génériques utilisent les caractères "0e23ddf2cd2db17fefda28fe66f19a88" pour séparer les paramètres de type et les arguments de type (similaire à la syntaxe du modèle C). Les types construits peuvent parfois être imbriqués, comme Listdd77601bbe5f7db04992ba7b2f8dd60c>, mais il existe quelques problèmes de syntaxe subtils lors de l'utilisation de cette construction : le lexeur combinera les deux derniers jetons de cette construction, ">>" shift opérateur ) au lieu de produire les deux balises ">" requises par la syntaxe. Bien qu'une solution possible consiste à mettre des espaces entre les deux ">>", cela est également gênant et déroutant et n'augmente en rien la simplicité du programme.
Afin de conserver la simplicité lexicale de ces constructions neutres, les marqueurs ">>" et ">>=" ont été supprimés du lexique et remplacés par des productions d'affectation à droite et à droite.
Opérateur ou ponctuation : l'un des
{ } [ ] ( ) , : ;
- * / % & ^ != c8fa30c56d0a6b6d6017db05e2d4e757
!= b207bb093495751f3e536c5eb7122819= = -= *= /= %= &= |=
^= 372b4682d8a7f87b35e525e4054b49f4 >
right-shift-assignment : (right-shift affectation)
> >=
Contrairement aux autres productions dans la syntaxe, en right-shift et Non les caractères de toute sorte (même les espaces) sont autorisés entre les jetons dans une production d'affectation par décalage à droite.

La production suivante est modifiée en utilisant le décalage à droite ou l'affectation du décalage à droite.
shift-expression : (shift expression :)
expression additive (expression supplémentaire)
shift-expression 7fbe2248f1ec08a34811011634c17426
ddd0620b42f67e0c3fae74991e3d1d10=
<=

(Pan Fin du type)
******** ********************

Ce qui précède est la spécification C# 2.0 (type général 6), veuillez faire attention au site Web PHP chinois (www.php.cn) pour plus de contenu connexe !


Déclaration:
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn