web-dev-qa-db-fra.com

Pourquoi les paramètres facultatifs C # 4 définis sur l'interface ne sont-ils pas appliqués lors de l'implémentation de la classe?

J'ai remarqué qu'avec les paramètres facultatifs de C # 4, si vous spécifiez un paramètre comme facultatif sur une interface, vous n'avez PAS à le rendre facultatif dans aucune classe d'implémentation:

public interface MyInterface
{
    void TestMethod(bool flag = false);
}

public class MyClass : MyInterface
{
    public void TestMethod(bool flag)
    {
        Console.WriteLine(flag);
    }
}

et donc:

var obj = new MyClass();        
obj.TestMethod(); // compiler error

var obj2 = new MyClass() as MyInterface;
obj2.TestMethod(); // prints false

Est-ce que quelqu'un sait pourquoi les paramètres optionnels sont conçus pour fonctionner de cette façon?

D'un côté, je suppose que la capacité de remplacer les valeurs par défaut spécifiées sur les interfaces est utile, mais pour être honnête, je ne suis pas sûr que vous puissiez même spécifier des valeurs par défaut sur l'interface, car cela devrait être une décision d'implémentation.

D'autre part, cette déconnexion signifie que vous ne pouvez pas toujours utiliser la classe concrète et l'interface de manière interchangeable. Bien entendu, cela ne poserait pas de problème si la valeur par défaut est spécifiée dans l'implémentation, mais si vous exposez votre classe concrète en tant qu'interface (à l'aide de la structure IOC permettant d'injecter la classe concrète exemple) alors il n’ya vraiment aucun intérêt à avoir la valeur par défaut car l’appelant devra toujours la fournir de toute façon.

344
theburningmonk

UPDATE: Cette question a été le sujet de mon blog le 12 mai 2011. Merci pour cette excellente question!

Supposons que vous ayez une interface telle que vous la décrivez et cent classes qui l'implémentent. Ensuite, vous décidez de rendre facultatif l'un des paramètres de l'une des méthodes de l'interface. Êtes-vous en train de suggérer que la bonne chose à faire est que le compilateur force le développeur à trouver chaque implémentation de cette méthode d'interface et rende le paramètre facultatif également?

Supposons que nous l'ayons fait. Supposons maintenant que le développeur ne dispose pas du code source pour la mise en œuvre:


// in metadata:
public class B 
{ 
    public void TestMethod(bool b) {}
}

// in source code
interface MyInterface 
{ 
    void TestMethod(bool b = false); 
}
class D : B, MyInterface {}
// Legal because D's base class has a public method 
// that implements the interface method

Comment l'auteur de D est-il supposé faire ce travail? Est-il nécessaire dans votre monde d'appeler l'auteur de B au téléphone et de leur demander de bien vouloir leur envoyer une nouvelle version de B qui donne à la méthode un paramètre facultatif?

Cela ne va pas voler. Que se passe-t-il si deux personnes appellent l'auteur de B, et l'une d'entre elles veut que la valeur par défaut soit vraie et l'autre d'entre elles, que ce soit faux? Que se passe-t-il si l'auteur de B refuse simplement de jouer?

Peut-être que dans ce cas ils seraient obligés de dire:

class D : B, MyInterface 
{
    public new void TestMethod(bool b = false)
    {
        base.TestMethod(b);
    }
}

La fonctionnalité proposée semble ajouter beaucoup d'inconvénients au programmeur, sans augmentation correspondante de la puissance représentative. Quel est l'avantage irrésistible de cette fonctionnalité qui justifie l'augmentation des coûts pour l'utilisateur?

226
Eric Lippert

Un paramètre facultatif est simplement étiqueté avec un attribut. Cet attribut indique au compilateur d'insérer la valeur par défaut pour ce paramètre sur le site de l'appel.

L'appel obj2.TestMethod(); est remplacé par obj2.TestMethod(false); lorsque le code C # est compilé en IL, et non au moment de JIT.

D'une certaine manière, l'appelant fournit toujours la valeur par défaut avec des paramètres facultatifs. Cela a également des conséquences sur la gestion des versions binaires: si vous modifiez la valeur par défaut mais ne recompilez pas le code d'appel, il continuera d'utiliser l'ancienne valeur par défaut.

D'autre part, cette déconnexion signifie que vous ne pouvez pas toujours utiliser la classe concrète et l'interface de manière interchangeable.

Vous ne pouvez déjà pas faire cela si la méthode d'interface était implémentée explicitement .

46
CodesInChaos

Parce que les paramètres par défaut sont résolus au moment de la compilation, pas à l'exécution. Ainsi, les valeurs par défaut n'appartiennent pas à l'objet appelé, mais au type de référence via lequel il est appelé.

28
Olhovsky

Les paramètres facultatifs sont un peu comme une substitution de macro de ce que je comprends. Ils ne sont pas vraiment optionnels du point de vue de la méthode. Un artefact de cela est le comportement que vous voyez où vous obtenez des résultats différents si vous transposez une interface.

5
Ariel Arjona