Que signifie le mot-clé' new ' lorsqu'il est utilisé dans une interface en C#?
Développer une interface générique je voulais déclarer un constructeur dans une interface mais il dit que les constructeurs sont interdits là-bas. J'ai essayé de déclarer une méthode d'usine statique alors, mais il dit qu'aucune des méthodes statiques n'est autorisée et suggère d'utiliser le mot-clé 'new'. Mais je n'ai presque aucune idée de ce que le mot-clé "Nouveau" pourrait signifier exactement lorsqu'il est utilisé dans une interface en C#. Avez-vous?
Mise à jour:
Je n'ai pas posté d'exemple de code parce que je ne voulais pas mélanger 2 questions-comment spécifiez un constructeur / usine dans une interface et que signifie le mot-clé' new ' dans les interfaces. J'ai même été obligé de spécifier la première partie parce que StackOverflow n'a pas accepté la deuxième question sous forme pure, en disant qu'elle ne répond pas aux normes de qualité.
Mais, comme vous l'exigez, je vais goûter à ce que j'essayais de réaliser:
Interface IMyInterface <T, U, V>
{
IMyInterface (T, U, U);
// OR
static IMyInterface GetNewIMyInterface (T, U, U);
}
Je veux juste que chaque classe dérivée implémente un tel constructeur.
7 réponses
Le mot clé new
indique au compilateur que votre définition cache la définition contenue dans les interfaces que votre interface peut étendre.
Bala réponse est bonne, mais il pourrait être utile de voir pourquoi vous voulez le faire. Considérez le problème auquel les concepteurs de BCL ont été confrontés lors de la conception des bibliothèques pour la version 2 de CLR. Il y avait une interface existante:
interface IEnumerable
{
IEnumerator GetEnumerator();
}
Maintenant, vous voulez ajouter:
interface IEnumerable<T> : IEnumerable
{
new IEnumerator<T> GetEnumerator();
}
La nouvelle interface diffère de l'ancienne uniquement par le type de retour.
Quels sont vos choix?
1) marquez le nouveau GetEnumerator comme "nouveau" afin que le compilateur sache que cela est prévu être la nouvelle méthode qui n'est pas en conflit avec l'ancienne méthode du même nom mais un type de retour différent.
2) changez le nom en GetEnumerator2.
3) Ne pas hériter de l'original IEnumerable.
Les Options 2 et 3 sont horribles. L'Option 1 est géniale: les nouveaux énumérables fonctionnent de manière transparente avec le code qui attend les anciens énumérables, mais le code écrit pour utiliser les nouveaux énumérables obtient le" nouveau " comportement générique par défaut.
Vous ne pouvez pas spécifier un constructeur ou une méthode statique dans une interface... ce que vous peut faire est d'ajouter une contrainte de type pour un paramètre de type générique, par exemple
void Foo<T>() where T : new()
{
T t = new T();
// Do stuff with t
}
C'est à ça que tu penses?
Une interface est censée spécifier un contrat. Il ne contiendra que des signatures de méthode et aucune implémentation. Une interface ne peut pas être instanciée directement, par conséquent un constructeur n'est pas autorisé dans une interface.
Http://msdn.microsoft.com/en-us/library/87d83y5b(v=vs. 80).aspx
Vous utilisez une interface, mais il semble que vous vouliez une classe de base à la place. Une interface ne devrait jamais avoir besoin d'un constructeur, car elle ne peut contenir aucun champ qui devrait être initialisé dans le constructeur. Je pense que vous voulez utiliser une classe de base à la place.
C # et. NET ne vous permet pas de déclarer un constructeur sur une interface.
Il doit simplement s'agir d'une contrainte déclarée d'implémentation de cette interface (voir ISerializable dans les bibliothèques. net).
Si vous y réfléchissez, avoir un constructeur sur une interface n'a pas de sens, car vous devez connaître la classe concrète que vous voulez créer lorsque vous appelez le constructeur. Comment allez-vous appeler un tel constructeur d'interface, et quel serait le résultat?
Tout d'abord, la seule chose que fait réellement le mot-clé 'new' est d'inviter le compilateur à ne pas produire d'avertissement indiquant que vous devez utiliser le mot-clé 'new'. En dehors de se débarrasser de l'avertissement, le mot-clé lui-même ne fait rien (dans le contexte en question).
Maintenant, le compilateur veut que vous utilisiez le mot-clé ' new ' lorsque vous redéfinissez un membre (propriété ou méthode) déjà défini dans une interface dont vous héritez, et il y a au moins deux raisons possibles pour le faire. Tout d'abord, comme Eric Lippert mentionné ci-dessus, vous pouvez souhaiter qu'une méthode renvoie un type différent (ou définisse une propriété du même nom avec un type différent). Une autre possibilité est si vous voulez définir différentes implémentations pour les deux interfaces:
interface A
{
void a();
}
interface B : A
{
new void a();
}
class C : B
{
void A.a() { Console.WriteLine("Called by interface A!"); }
void B.a() { Console.WriteLine("Called by interface B!"); }
}
static class Test
{
public static void DoTest()
{
B b = new C();
b.a(); // Produces "Called by interface B!"
((A)b).a(); // Produces "Called by interface A!"
}
}
Si vous essayez de définir B.a()
dans C sans redéfinir a()
dans B, vous obtenez un avertissement qu'il n'est pas membre de l'interface: une déclaration explicite d'interface requiert l'utilisation d'une interface pour laquelle le membre est explicitement définie.