web-dev-qa-db-fra.com

Une méthode statique peut-elle être remplacée en C #?

On m'a dit que les méthodes static sont implicitement final et ne peuvent donc pas être remplacées. Est-ce vrai?

  1. Quelqu'un peut-il donner un meilleur exemple de remplacement d'une méthode statique?

  2. Si les méthodes statiques ne sont que des méthodes de classe, quelle est l'utilité réelle de les avoir?

34
aspiring

(1) Les méthodes statiques ne peuvent pas être remplacées, elles peuvent cependant être masquées à l'aide du mot-clé 'new'. La plupart du temps, les méthodes écrasantes signifient que vous référencez un type de base et que vous souhaitez appeler une méthode dérivée. Étant donné que les statiques font partie du type et ne sont pas soumis à des recherches vtables, cela n'a aucun sens.

Par exemple. la statique ne peut pas faire:

public class Foo { 
    public virtual void Bar() { ... }
}
public class Bar : Foo {
    public override void Bar() { ... }
}

// use:
Foo foo = new Bar(); // make an instance
foo.Bar(); // calls Bar::Bar

Étant donné que la statique ne fonctionne pas sur les instances, vous spécifiez toujours Foo.Bar ou Bar.Bar explicitement. La substitution n'a donc aucun sens ici (essayez de l'exprimer en code ...).

(2) Il existe différentes utilisations des méthodes statiques. Par exemple, il est utilisé dans le modèle Singleton pour obtenir une seule instance d'un type. Un autre exemple est "static void Main", qui est le principal point d'accès de votre programme.

Fondamentalement, vous les utilisez chaque fois que vous ne voulez pas ou ne pouvez pas créer une instance d'objet avant de l'utiliser. Par exemple, lorsque la méthode statique crée l'objet.

[mise à jour]

Un exemple de masquage simple:

public class StaticTest
{
    public static void Foo() { Console.WriteLine("Foo 1"); }
    public static void Bar() { Console.WriteLine("Bar 1"); }
}

public class StaticTest2 : StaticTest
{
    public new static void Foo() { Console.WriteLine("Foo 2"); }
    public static void Some() { Foo(); Bar(); } // Will print Foo 2, Bar 1
}

public class TestStatic
{
    static void Main(string[] args)
    {
        StaticTest2.Foo();
        StaticTest2.Some();
        StaticTest.Foo();
        Console.ReadLine();
    }
}

Notez que si vous créez les classes static, vous ne pouvez pas le faire. Les classes statiques doivent dériver de object.

La principale différence entre cela et l'héritage est que le compilateur peut déterminer au moment de la compilation quelle méthode appeler lors de l'utilisation de static. Si vous avez des instances d'objets, vous devez le faire lors de l'exécution (ce qui est appelé une recherche vtable).

32
atlaste

Vous ne remplacez pas une méthode statique. Tu le caches. Voir cette réponse pour plus d'informations.

Quelques raisons d'utiliser des méthodes statiques:

  1. Elles sont n peu plus rapides que les méthodes d'instance. Voir également ceci article msdn qui donne des chiffres de performance pour sauvegarder cela (appel statique en ligne moyen 0,2 ns, appel statique en moyenne 6,1 ns, appel en instance en ligne moyen 1,1 ns, appel en instance moyen 6,8 ns)
  2. Moins verbeux à écrire - pas besoin d'instancier une classe pour y accéder (et l'instanciation peut également affecter les performances)
5
Yaakov Ellis

Eh bien, vous ne pouvez pas remplacer une méthode statique. Une méthode statique ne peut pas être virtuelle, car elle n'est pas liée à une instance de la classe.

La méthode "surchargée" dans la classe dérivée est en fait une nouvelle méthode, sans rapport avec celle définie dans la classe de base (d'où le nouveau mot-clé).

C'est une chose importante à comprendre: lorsque les types héritent d'autres types, ils remplissent un contrat commun, tandis que les types statiques ne sont liés par aucun contrat (du point de vue pur OOP). Il y a aucun moyen technique dans la langue de lier deux types statiques avec un contrat "d'héritage". Si vous "surchargez" la méthode Log à deux endroits différents.

Si vous pensez à remplacer les méthodes statiques, cela n'a pas vraiment de sens; afin d'avoir une répartition virtuelle, vous avez besoin d'une instance réelle d'un objet à comparer.

Une méthode statique ne peut pas non plus implémenter une interface; si cette classe implémente une interface IRolesService, je dirais que la méthode ne doit pas du tout être statique. Il est préférable de disposer d'une méthode d'instance, vous pouvez donc échanger votre MockRoleService avec un vrai service lorsque vous êtes prêt

5
Neel