web-dev-qa-db-fra.com

Avantages de l'utilisation de méthodes statiques privées

Lors de la création d'une classe ayant des méthodes privées internes, généralement pour réduire la duplication de code, qui ne nécessite pas l'utilisation de champs d'instance, existe-t-il des avantages en termes de performances ou de mémoire pour déclarer la méthode statique?

Exemple:

foreach (XmlElement element in xmlDoc.DocumentElement.SelectNodes("sample"))
{
    string first = GetInnerXml(element, ".//first");
    string second = GetInnerXml(element, ".//second");
    string third = GetInnerXml(element, ".//third");
}

...

private static string GetInnerXml(XmlElement element, string nodeName)
{
    return GetInnerXml(element, nodeName, null);
}

private static string GetInnerXml(XmlElement element, string nodeName, string defaultValue)
{
    XmlNode node = element.SelectSingleNode(nodeName);
    return node == null ? defaultValue : node.InnerXml;
}

Est-il avantageux de déclarer les méthodes GetInnerXml () statiques? Pas de réponse d'opinion s'il vous plaît, j'ai une opinion.

192
NerdFury

À partir de la page de règle FxCop à ce sujet:

Une fois que vous avez marqué les méthodes comme statiques, le compilateur émettra des sites d'appels non virtuels à ces membres. L'émission de sites d'appels non virtuels empêchera une vérification au moment de l'exécution de chaque appel garantissant que le pointeur d'objet actuel est non nul. Cela peut entraîner un gain de performance mesurable pour un code sensible à la performance. Dans certains cas, l'impossibilité d'accéder à l'instance d'objet en cours représente un problème de correction.

203
Scott Dorman

Quand j'écris un cours, la plupart des méthodes se divisent en deux catégories:

  • Méthodes qui utilisent/modifient l'état de l'instance actuelle.
  • Des méthodes d'assistance qui n'utilisent/modifient pas l'état de l'objet actuel, mais m'aident à calculer les valeurs dont j'ai besoin ailleurs.

Les méthodes statiques sont utiles car, en regardant simplement sa signature, vous savez que l'appelant n'utilise ni ne modifie l'état de l'instance actuelle.

Prenons cet exemple:

classe publique Library 
 {
 private static Book findBook (Liste <Livre> livres, titre de chaîne) 
 {
 // code va ici 
} 
}

Si une instance de l'état de la bibliothèque se casse jamais, et j'essaie de comprendre pourquoi, je peux exclure findBook comme le coupable, juste à partir de sa signature.

J'essaie de communiquer le plus possible avec la signature d'une méthode ou d'une fonction, et c'est un excellent moyen de le faire.

86
Neil

Un appel à une méthode statique génère une instruction d'appel en langage intermédiaire Microsoft (MSIL), alors qu'un appel à une méthode d'instance génère une instruction callvirt, qui recherche également les références null à un objet. Cependant, la plupart du temps, la différence de performance entre les deux n'est pas significative.

src: MSDN - http://msdn.Microsoft.com/en-us/library/79b3xss3 (v = vs.110) .aspx

78
Marek Takac

Oui, le compilateur n'a pas besoin de passer le pointeur implicite this aux méthodes static. Même si vous ne l'utilisez pas dans votre méthode d'instance, il est toujours transmis.

14
Kent Boogaart

Ce sera un peu plus rapide car aucun paramètre n’est passé (bien que le coût de la performance de l’appel de la méthode soit probablement beaucoup plus élevé que cette économie).

Je dirais que la meilleure raison à laquelle je puisse penser pour les méthodes statiques privées est que cela signifie que vous ne pouvez pas modifier l'objet par inadvertance (car il n'y a pas de pointeur).

5
Free Wildebeest

Cela vous oblige à ne pas oublier de déclarer également tous les membres de classe affectés par la fonction que la fonction utilise également en tant que statique, ce qui devrait vous permettre d'économiser de la mémoire lors de la création de ces éléments pour chaque instance.

4
Joel Coehoorn

Je préfère de loin que toutes les méthodes privées soient statiques, sauf si elles ne peuvent vraiment pas l'être. Je préférerais de beaucoup ce qui suit:

public class MyClass
{
    private readonly MyDependency _dependency;

    public MyClass(MyDependency dependency)
    {
        _dependency = dependency;
    }

    public int CalculateHardStuff()
    {
        var intermediate = StepOne(_dependency);
        return StepTwo(intermediate);
    }

    private static int StepOne(MyDependency dependency)
    {
        return dependency.GetFirst3Primes().Sum();
    }

    private static int StepTwo(int intermediate)
    {
        return (intermediate + 5)/4;
    }
}

public class MyDependency
{
    public IEnumerable<int> GetFirst3Primes()
    {
        yield return 2;
        yield return 3;
        yield return 5;
    }
}

sur chaque méthode accédant au champ d'instance. Pourquoi est-ce? Comme ce processus de calcul devient plus complexe et que la classe se termine avec 15 méthodes d'assistance privée, je souhaite VRAIMENT pouvoir les extraire dans une nouvelle classe qui encapsule un sous-ensemble d'étapes de manière sémantique.

Lorsque MyClass obtient davantage de dépendances parce que nous avons besoin de la journalisation et devons également notifier un service Web (veuillez excuser les exemples de clichés), il est alors très utile de voir facilement quelles méthodes ont des dépendances.

Des outils tels que R # vous permettent d'extraire une classe d'un ensemble de méthodes statiques privées en quelques frappes. Essayez de le faire lorsque toutes les méthodes d'assistance privée sont étroitement liées au champ d'instance et vous verrez que cela peut être un casse-tête.

2
sara