2017-02-24 4 views
3

Lorsque j'appelle une fonction et remplace l'un des paramètres par dynamique, le compilateur infère que le résultat de la fonction est dynamique. Je ne comprends pas pourquoi cela arrive.Inférence de type compilateur C# avec paramètres de fonction dynamique

Exemple: le type inféré pour une dynamique, de sorte que ce code compile, mais bien sûr échoue à l'exécution avec RuntimeBinderException:

dynamic b = ""; 
var a = MethodWithoutOverloads("", b); 
a.DoesNotExist(); 

...

public string MethodWithoutOverloads(string a, string b) { ... } 

Quelqu'un sait pourquoi le type inféré n'est pas le type de retour de la fonction?

EDIT: sous la direction de préciser ce qui se passe avec des méthodes sans

Répondre

1

Vous avez raison dans le sens que le compilateur pourrait raison que tous String.Format un retour string surcharge et donc en déduire que a doit être une chaîne, peu importe ce que b est vraiment.

La vérité est que le compilateur ne fait pas cela. Il résout le cas général, ce qui est bien, et parce que les surcharges avec des types de retour différents sont valides en C#, il affecte simplement le type de retour comme dynamique et laisse le temps d'exécution le comprendre.

Répondre à votre question,

public string MethodWithoutOverloads(string a, string b) { ... } 
dynamic a = ""; 
var result = MethodWithoutOverloads(a, a); // result is dynamic. 

le compilateur laisse imaginer décide que result est string et que vous publiez à l'ouest sauvage de votre bibliothèque. Puis, plus tard, vous décidez d'ajouter une surcharge avec la signature suivante:

public int MethodWithoutOverloads(int a, int b) { ... } 

Maintenant, quel devrait être le type de result être? Et, qu'arrive-t-il au code existant qui s'appuyait sur result étant fortement typé à string?

string result = MethodWithoutOverloads(someDynamicVariable, someOtherDynamicVariable); 

La sémantique change complètement; Avant qu'un consommateur n'ait une variable fortement typée, il a soudainement une distribution implicite potentiellement dangereuse qui peut exploser en cours d'exécution.

0
surcharge

Parce que le compilateur ne sait pas quelle méthode va être invoqué au moment de l'exécution.

Par exemple, vous pouvez avoir les deux méthodes:

int MyMethod(int a) 
{ 
    return 5; 
} 

double MyMethod(string a) 
{ 
    return 6.0; 
} 

Et vous écrivez le code suivant:

dynamic myThing = 5; 
var myResult = MyMethod(myThing); 

Vu que nous avons dit explicitement myThing est dynamique, et ce son Le type doit être déterminé à l'exécution, nous n'avons aucune idée de la méthode qui sera invoquée (le cas échéant). Ainsi, nous ne connaissons pas non plus le type de retour.

+0

Cela se produit lorsque j'ai une méthode, c'est-à-dire lorsqu'il n'y a pas d'ambiguïté. String.Format n'est pas un bon exemple, mais l'inférence de type échoue également lorsque j'appelle ma propre méthode lorsqu'il n'y a pas d'ambiguïté. – Lev

+1

@Lev C'est correct.* Techniquement * le compilateur peut être capable de le comprendre sans ambiguïté, mais je suppose que cela nécessiterait beaucoup plus de travail pour apparemment pas beaucoup de gain. Chaque fois que 'dynamic' fait partie d'une expression, le résultat sera aussi' dynamic'. Si vous êtes sûr de connaître le type, soyez simplement explicite avec le type de variable plutôt que d'utiliser 'var' – Rob

+0

Ok donc, fondamentalement, c'est un cas de" nous n'avons pas implémenter l'inférence de type pour ce cas "... – Lev