6
votes

Pourquoi le constructeur statique de la classe mère n'a-t-il pas appelé lorsqu'il invoque une méthode sur une classe imbriquée?

Compte tenu du code suivant, pourquoi le constructeur statique de "externe" n'est-il pas appelé après la première ligne de "principale"?

namespace StaticTester
{
    class Program
    {
        static void Main( string[] args )
        {
            Outer.Inner.Go();
            Console.WriteLine();

            Outer.Go();

            Console.ReadLine();
        }
    }

    public static partial class Outer
    {
        static Outer()
        {
            Console.Write( "In Outer's static constructor\n" );
        }

        public static void Go()
        {
            Console.Write( "Outer Go\n" );
        }

        public static class Inner
        {
            static Inner()
            {
                Console.Write( "In Inner's static constructor\n" );
            }

            public static void Go()
            {
                Console.Write( "Inner Go\n" );
            }
        }
    }
}


0 commentaires

4 Réponses :


3
votes

Outer.inner se réfère simplement à un type, cela n'appellait rien sur "extérieur".


1 commentaires

J'ai dit cela ici, d'autres autres ne réfléchissent pas aussi longtemps que moi.



0
votes

Un initialiseur statique n'est exécuté que lorsque la classe contenant est utilisée pour la première fois.

en appelant extérieur.inner , vous n'utilisez pas externe du tout, car externe.inner est un type différent de celui de Extérieur . Donc, l'initialisateur statique dans externe ne fonctionnera pas.


1 commentaires

Ah, n'a pas vu ton commentaire là-bas :)



5
votes

dans le cas de classes imbriquées, si la classe imbriquée ne fait jamais référence aux membres statiques de sa portée extérieure, le compilateur (et le CLR) ne doit pas nécessairement appeler le constructeur statique de cette classe extérieure.

Si vous souhaitez forcer le constructeur statique à exécuter, il suffit d'ajouter du code au type interne qui effectue une lecture d'un champ ou d'une propriété du type externe.

Vous pouvez en savoir plus sur la sémantique de l'initialisation paresseuse de C # sur Blog de Jon Skeet - C'est assez bien. Vous pouvez également consulter son livre - C # en profondeur , il couvre ces sujets ... dans Profondeur.


1 commentaires

C'est drôle, j'ai sorti ma copie de C # en profondeur pour aider à comprendre pourquoi.



7
votes

Votre question est répondue à la section 10.12 de la spécification, qui indique:

L'exécution d'un constructeur statique est déclenché par le premier de la événements suivants à se produire dans un Domaine d'application:

• une instance de Le type de classe est créé.

• n'importe lequel des les membres statiques du type de classe sont référencés.

Puisque vous n'avez rien fait de ces deux choses, le CTOR n'est pas exécuté.


4 commentaires

Mais est interne non membre de externe ? Et interne est référencé. Sûrement interne n'est pas une instance MEMBR? Alors n'est-ce pas un membre statique? Peut-être que des classes imbriquées ne doivent pas être considérées comme des membres à cet égard?


@Jeppestignielsen: Vous faites un bon point; J'étais imprécis. J'aurais dû dire l'un des champs statiques , méthodes, propriétés, événements, indexeurs ou opérateurs .


Vous avez cité la spécification précisément. Donc, vous dites vraiment que la spécification est imprécise (ou peut-être que vous dites que vous avez écrit cette partie de la spécification)? Ou peut-être des types imbriqués ne doivent pas être considérés comme des membres dans ce contexte.


@Jeppestignielsen: La spécification pourrait être reformulée pour la rendre plus claire. Je vais le mentionner à Mads.