54 votes

Pourquoi ne pouvez-vous pas utiliser 'ceci' dans les initialiseurs de membres?

Double Possible:
Ne peut pas utiliser " il " dans l'initialiseur de membre?

Des idées pourquoi j'obtiens un message d'erreur si j'essaie de faire quelque chose comme ceci:

public class Bar
{
    public Bar(Foo foo)
    {
    }
}

public class Foo
{
    private Bar _bar = new Bar(this);
}

J'obtiens un message d'erreur disant:

"Ne peut pas utiliser" il "dans l'initialiseur de membre"

mais les ouvrages suivants:

public class Foo
{
    private Bar _bar;

    public Foo()
    {
        _bar = new Bar(this);
    }
}

Quelqu'un sait la raison derrière tout cela? Ma compréhension était que ces compiler à la même IL, je suis curieux de savoir pourquoi l'un est autorisé et l'autre ne l'est pas.

Merci, Alex

54voto

Jon Skeet Points 692016

Je soupçonne que c'est pour empêcher l'utilisation de l'objet avant au moins le constructeur de classe de base a terme, veiller à ce que tous les membres de classe de base sont correctement initialisés. (Variable initialiseurs sont exécutés avant le constructeur de classe de base, tandis que le corps du constructeur est exécuté après que.)

Va vérifier si le annoté spec a rien à dire à ce sujet quand je suis à côté près d'elle...

EDIT: Le C# 4 annoté spec n'est pas une explication. Juste (dans 10.5.5.2):

Une variable d'initialisation d'une instance de champ ne peut pas faire référence à l'instance en cours de création.

14voto

Darin Dimitrov Points 528142

Champ d'initialiseurs de s'exécuter avant de la classe de base des constructeurs de sorte this n'existe pas encore. Il existe seulement une fois que le constructeur de base a fini de s'exécuter.

17.10.2 variable d'Instance initialiseurs:

Lorsqu'une instance constructeur n'a pas constructeur de l'initialiseur, ou il a un constructeur de l'initialiseur de la forme de base(...), que le constructeur implicitement effectue les initialisations spécifié par la variable-les initialiseurs de l' champs d'instance a déclaré dans sa classe. Cela correspond à une séquence de les affectations qui sont exécutées dès l'entrée à l' le constructeur et l'avant de l'implicite l'invocation de la classe de base directe constructeur. La variable les initialiseurs sont exécutées dans le ordre textuel dans lequel ils apparaissent dans la déclaration de classe.

0voto

F.B. ten Kate Points 1119

Je pense que cela est dû au fait que les champs sont initialisés avant la classe alors que le code suivant est exécuté:

 private Bar _bar = new Bar(this);
 

"this" n'a aucune valeur réelle à référencer.

Bien que le mettre dans le constructeur signifie qu’il existe une instance de "Foo" référencable par "this"

0voto

Matías Fidemraizer Points 16842

En C#, pas de logique est destiné à être à l'extérieur des méthodes et des propriétés des corps.

Champ initialiseurs sont une exception, mais avec quelques limitations.

Il avait mal à obtenir une référence d'objet courant avec ce mot-clé, car un champ de classe de la déclaration n'est pas de la logique mais de conception de classe, alors que ce est une partie de la durée d'exécution de la sémantique.

Par le façon, il semble que c'est un C# design décision, parce que, en fait, un champ d'initialiseur s'exécute pendant le cours de la construction, de sorte que "l'instance courante de la classe de déclaration" devrait être disponible par le biais de cette. Mais à nouveau, ce serait présente à l'extérieur une méthode ou une propriété du corps de la portée?

Comme Jon Skeet et d'autres ont fait, ce n'est pas disponible car le champ des initialiseurs sont exécutées après le constructeur de base de l'exécution.

0voto

Truong Hong Thi Points 156

Les initialiseurs de membres s'exécutent avant le constructeur de la classe. Considérez que vous pouvez avoir plusieurs initialiseurs de membres dans une même classe.

Si vous utilisez 'this' dans constructeur -> tous les membres avec les initialiseurs ont été initialisés. Donc tout va bien.

Si vous utilisez 'this' dans membre initializer: d'autres membres (avec des initialiseurs attachés) peuvent ne pas encore être initialisés -> 'this' n'est pas encore prêt. C'est pourquoi l'utilisation de 'ceci' n'est pas autorisée ici n'est pas autorisée.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X