110 votes

Pourquoi le compilateur c# ne pas blâmer code où une méthode statique appelle une méthode d’instance ?

Le code suivant est une méthode statique, Foo(), à l'appel d'une méthode d'instance, Bar():

public sealed class Example
{
    int count;

    public static void Foo( dynamic x )
    {
        Bar(x);
    }

    void Bar( dynamic x )
    {
        count++;
    }
}

Il se compile sans erreur* mais génère un runtime liant exception à l'exécution. Retrait de la dynamique paramètre de ces méthodes provoque une erreur de compilation, comme prévu.

Alors pourquoi le fait d'avoir un paramètre dynamique permettent le code à compiler? ReSharper n'apparaît pas comme une erreur.

Edit 1: *dans Visual Studio 2008

Edit 2: ajout sealed puisqu'il est possible qu'une sous-classe peut contenir une statique Bar(...) méthode. Même la version étanche compile quand il n'est pas possible que toute autre méthode que la méthode d'instance qui pourrait être appelé lors de l'exécution.

71voto

Jeppe Stig Nielsen Points 17887

Pour une raison quelconque, la résolution de surcharge trouve toujours le meilleur match avant de vérification statique versus non-statique. S'il vous plaît essayez ce code avec tous les types statiques:

class SillyStuff
{
  static void SameName(object o) { }
  void SameName(string s) { }

  public static void Test()
  {
    SameName("Hi mom");
  }
}

Ce ne sera pas compiler, car le meilleur de surcharge est celui qui prend un string. Mais bon, c'est une méthode d'instance, de sorte que le compilateur se plaint (au lieu de prendre la deuxième meilleure de surcharge).

Plus: Donc, je pense que l'explication de l' dynamic exemple de la Question d'Origine, c'est que, dans un souci de cohérence, quand les types sont dynamiques, nous avons aussi la première à trouver la meilleure surcharge (vérification seul paramètre nombre et les types de paramètre, etc., pas statiques et non statiques), et seulement ensuite vérifier statique. Mais cela signifie que la statique de la case a à attendre jusqu'à ce que l'exécution. D'où le comportement observé.

Ajout tardif: un peu de fond sur le pourquoi ils ont choisi de faire les choses de cette drôle de commande peut être déduit de ce blog par Eric Lippert.

30voto

Marc Gravell Points 482669

Toto a un paramètre "x", c'est dynamique, ce qui signifie Bar(x) est une expression dynamique.

Il serait tout à fait possible par Exemple d'avoir des méthodes comme:

static Bar(SomeType obj)

Auquel cas la bonne méthode serait résolu, de sorte que la déclaration de la Barre(x) est parfaitement valide. Le fait qu'il y est une méthode d'instance de la Barre(x) est sans importance et même pas envisagé: par définition, puisque la Barre(x) est une expression dynamique, nous avons reporté la résolution de l'exécution.

9voto

oberfreak Points 1467

La "dynamique" de l'expression sera lié au cours de l'exécution, si l'on définit une méthode statique avec la signature correcte ou une méthode d'instance, le compilateur ne vérifie pas.

La "bonne" méthode sera déterminée lors de l'exécution. Le compilateur ne peut pas savoir si il existe une méthode valable, il en cours d'exécution.

La "dynamique" mot-clé est définie pour la dynamique et des langages de script, dont la Méthode peut être définie, à tout moment, même en cours d'exécution. Truc de dingue

Voici un exemple qui s'occupe de l'ints, mais pas de chaînes, en raison de la méthode sur l'exemple.

class Program {
    static void Main(string[] args) {
        Example.Foo(1234);
        Example.Foo("1234");
    }
}
public class Example {
    int count;

    public static void Foo(dynamic x) {
        Bar(x);
    }

    public static void Bar(int a) {
        Console.WriteLine(a);
    }

    void Bar(dynamic x) {
        count++;
    }
}

Vous pouvez ajouter une méthode pour gérer tous les "mauvais" des appels, qui ne peut pas être traitée

public class Example {
    int count;

    public static void Foo(dynamic x) {
        Bar(x);
    }

    public static void Bar<T>(T a) {
        Console.WriteLine("Error handling:" + a);
    }

    public static void Bar(int a) {
        Console.WriteLine(a);
    }

    void Bar(dynamic x) {
        count++;
    }
}

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