Pourquoi une classe C # peut-elle hériter d'une interface à la fois implicitement et explicitement?
-
05-07-2019 - |
Question
Aujourd'hui, je trouve qu'une classe C # peut hériter d'une interface de manière implicite et explicite. Cela me surprend. Si C # fonctionne de cette manière, une instance peut se comporter différemment si elle est référencée différemment.
interface IFoo
{
void DoSomething();
}
class Foo : IFoo
{
#region IFoo Members
public void DoSomething()
{
Console.WriteLine("do something implicitly");
}
#endregion
#region IFoo Members
void IFoo.DoSomething()
{
Console.WriteLine("do something explicitly");
}
#endregion
}
Foo f = new Foo();
f.DoSomething();
((IFoo)f).DoSomething();
Le code ci-dessus est exécuté et généré
do something implicitly
do something explicitly
Je pense que cette conception de C # crée une incohérence de comportement. Peut-être est-il obligatoire qu'une classe C # puisse hériter d'une interface de manière implicite ou explicite, mais pas des deux.
Existe-t-il une raison pour laquelle C # est conçu de cette manière?
La solution
Votre exemple ne met pas en œuvre IFoo de manière implicite et explicite. Vous implémentez uniquement IFoo.DoSometing () explicitement. Vous avez une nouvelle méthode sur votre classe appelée DoSomething (). Cela n'a rien à voir avec IFoo.DoSomething, sauf qu'il porte le même nom et les mêmes paramètres.
Autres conseils
Chaque classe qui implémente une interface a un mappage entre les membres de cette classe et les membres de l'interface. Si la classe explicitement implémente un membre d'interface, l'implémentation explicite sera toujours mappée sur l'interface. S'il n'y a pas d'implémentation explicite, une implémentation implicite est attendue et sera mise en correspondance avec l'interface.
Lorsqu'une classe a le même nom de membre et les types associés qu'une interface mais , elle implémente aussi explicitement le membre correspondant pour l'interface, puis la " implicite " de la classe. L'implémentation n'est pas considérée comme une implémentation de l'interface du tout (à moins que l'implémentation explicite ne l'appelle).
En plus des significations différentes dans chaque cas où la classe implémente plusieurs interfaces avec le même nom / type de membre, même avec une seule interface, la classe elle-même est considérée comme ayant une interface implicite pouvant avoir les mêmes membres / types que la seule interface, mais signifie toujours quelque chose de différent.
Cela le rend plus flexible pour les collisions. En particulier, consultez IEnumerator
et IEnumerator<T>
- ils ont tous deux une propriété Current
, mais de types différents . Vous devez utiliser l'implémentation d'interface explicite pour implémenter les deux (et la forme générique étend la forme non générique).
Héritage multiple: Que faire si vous dérivez de deux interfaces définissant la même méthode à des fins différentes?
interface IMoveable
{
public void Act();
}
interface IRollable
{
public void Act();
}
class Thing : IMoveable, IRollable
{
//TODO Roll/Move code here
void IRollable.Act()
{
Roll();
}
void IMoveable.Act()
{
Move();
}
}
Les gars, merci pour vos réponses.
Il s'avère que & "; La classe C # peut hériter d'une interface de manière implicite et explicite à la fois &"; est en fait une illusion. En fait, une classe peut hériter d'une interface pour une fois.
Dans la question initiale, le & "DoSomething &"; la méthode semble & "implémenter implicitement &"; interface IFoo (la méthode est en fait générée par VS2008), mais ce n’est pas réellement le cas. Avec l'implémentation explicite de l'interface IFoo, le & Quot; DoSomething & Quot; Cette méthode s'avère être simplement une méthode normale qui n'a rien à voir avec IFoo, sauf avec la même signature.
Je persiste à croire que la conception de C # est délicate et qu’il est facile de l’utiliser par erreur. Dis, j'ai un code comme ça
Foo f = new Foo();
f.DoSomething();
Maintenant, je veux le refactoriser en dessous du code. Cela me semble parfaitement correct, mais le résultat de l’exécution est différent.
Action<IFoo> func = foo => foo.DoSomething();
func(f);