Question

namespace MyNameSpace
{
    static class MyClass
    {
        static MyClass()
        {
            //Authentication process.. User needs to enter password
        }

        public static void MyMethod()
        {
            //Depends on successful completion of constructor
        }
    }

    class Program
    {
        static void Main(string[] args)
        {
            MyClass.MyMethod();
        }
    }
}

Voici la séquence que j'ai supposée

  1. Début du constructeur statique
  2. Fin du constructeur statique
  3. Début de la principale
  4. Début de MyMethod
  5. Fin de la principale

Maintenant dans n'importe quel scénario si 4 commencera avant 2 je suis foutu.Est-ce possible?

Était-ce utile?

La solution

Vous n'avez posé qu'une seule question ici, mais il y a une douzaine de questions que vous auriez dû avoir posées, je vais donc y répondre à toutes.

Voici la séquence que j'ai supposée

  1. Début du constructeur de classe (également appelé cctor)
  2. Fin du cctor
  3. début de Main
  4. début de MyMethod

Est-ce correct?

Non. La séquence correcte est:

  1. Début du cctor pour le programme, s'il y en a un. Il n'y en a pas.
  2. Fin du cctor pour Program, s'il y en a un. Il n'y en a pas.
  3. Début de Main
  4. Début du cctor pour MyClass
  5. Fin du cctor pour MyClass
  6. Début de MyClass.MyMethod

Et s'il existe un initialiseur de champ statique?

Le CLR est autorisé à changer l'ordre dans lequel les initialiseurs de champs statiques s'exécutent dans certains cas. Voir la page de Jon sur le sujet pour plus de détails:

Les différences entre les constructeurs statiques et les initialiseurs de type

Est-il possible qu'une méthode statique comme MyMethod soit appelée avant que le cctor de cette classe ne se termine?

Oui. Si le cctor lui-même appelle MyMethod alors évidemment MyMethod sera appelé avant la fin du cctor.

Le cctor n'appelle pas MyMethod. Est-il possible qu'une méthode statique comme MyMethod soit appelée avant que le cctor de MyClass ne se termine?

Oui. Si le cctor utilise un autre type dont le cctor appelle MyMethod, MyMethod sera appelé avant la fin du cctor MyClass.

Aucun ccteur n'appelle MyMethod, directement ou indirectement! Est-il désormais possible qu'une méthode statique comme MyMethod soit appelée avant que le cctor de MyClass ne se termine?

Non.

Est-ce toujours vrai même s'il y a plusieurs threads impliqués?

Oui. Le cctor se terminera sur un thread avant que la méthode statique puisse être appelée sur n'importe quel thread.

Le cctor peut-il être appelé plus d'une fois? Supposons que deux threads provoquent tous les deux l'exécution du cctor.

Il est garanti que le cctor sera appelé au plus une fois, quel que soit le nombre de threads impliqués. Si deux threads appellent MyMethod "en même temps", ils font la course. L'un d'eux perd la course et bloque jusqu'à ce que le contrôleur MyClass se termine sur le thread gagnant.

Le thread perdant bloque jusqu'à ce que le cctor soit terminé? Vraiment ?

Vraiment.

Et si le contrôleur du thread gagnant appelle du code qui se bloque sur un verrou précédemment pris par le thread perdant ?

Ensuite, vous avez une condition d'inversion d'ordre de verrouillage classique. Vos programmes sont bloqués. Pour toujours.

Cela semble dangereux. Comment éviter l'impasse?

Si cela vous fait mal, arrêtez de le faire . Ne faites jamais quelque chose qui peut bloquer dans un cctor.

Est-ce une bonne idée de s'appuyer sur la sémantique d'initialisation de cctor pour appliquer des exigences de sécurité complexes? Et est-ce une bonne idée d'avoir un cctor qui effectue les interactions des utilisateurs?

Les bonnes idées non plus. Mon conseil est que vous devriez trouver une manière différente de vous assurer que les conditions préalables ayant un impact sur la sécurité de vos méthodes sont remplies.

Autres conseils

Selon le MSDN , un constructeur statique:

Un constructeur statique est appelé automatiquement pour initialiser la classe avant que la première instance ne soit créée ou que des membres statiques soient référencé.

Donc, le constructeur statique sera appelé avant que la méthode statique MyClass.MyMethod() ne soit appelée (en supposant qu'elle ne soit pas également appelée pendant la construction statique ou l'initialisation du champ statique bien sûr).

Maintenant, si vous faites quoi que ce soit de manière asynchrone dans ce code générique, c'est à vous de le synchroniser.

Le n ° 3 est en fait le n ° 1: l'initialisation statique ne démarre pas avant la première utilisation de la classe à laquelle elle appartient.

C'est possible si MyMethod est appelé depuis le constructeur statique ou un bloc d'initialisation statique.Si vous n'appelez pas MyMethod directement ou indirectement à partir de votre constructeur statique, tout devrait bien se passer.

De la documentation (c'est moi qui souligne):

Un constructeur statique est appelé automatiquement pour initialiser la classe avant la création de la première instance , ou tout membre statique est référencé .

Vous pouvez garantir que 4 viendra toujours après 2 (si vous ne créez pas d'instance de votre classe à partir de votre méthode statique), mais il n'en va pas de même pour 1 et 3.

Le constructeur statique sera appelé avant l'exécution de ma méthode.Cependant, si vous êtes foutu si 4 est appelé avant 2, je vous suggère de repenser votre conception.De toute façon, ne devrait pas faire de choses compliquées dans un constructeur statique.

Le CLR garantit que le constructeur statique s'exécute avant l'accès à tout membre statique.Cependant, votre design est un peu malodorant.Ce serait plus simple de faire quelque chose comme ceci:

static void Main(string[] args) 
{ 
     bool userIsAuthenticated = MyClass.AuthenticateUser();
     if (userIsAuthenticated)
         MyClass.MyMethod(); 
 } 

Avec votre conception, si l'authentification échoue, le seul moyen d'empêcher MyMethod de s'exécuter est de lever une exception.

Il est garanti que le constructeur d'une classe statique a été appelé avant que l'une de ses méthodes ne soit exécutée.Exemple:

class Program
{
    static void Main(string[] args)
    {
        Console.WriteLine("Press enter");
        Console.ReadLine();
        Boop.SayHi();
        Boop.SayHi();
        Console.ReadLine();
    }

}

static class Boop
{
    static Boop()
    {
        Console.WriteLine("Hi incoming ...");
    }

    public static void SayHi()
    {
        Console.WriteLine("Hi there!");
    }
}

Sortie:

Appuyez sur Entrée

// après avoir appuyé sur Entrée

Bonjour à l'arrivée ...

Bonjour!

Bonjour!

Voici l'ordre réel dans lequel les choses se passent:

  1. Début du Main
  2. Début du constructeur statique MyClass
  3. Fin du constructeur statique MyClass
  4. Début du MyMethod
  5. Fin du Main

Ou vous pouvez accéder au débogueur.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top