Lorsque vous utilisez l'ildasm / ilasm, vous pouvez observer le code MSL / CIL produit par un compilateur (le compilateur C #, par exemple), et dans certains cas, vous pouvez voir qu'il existe des méthodes marquées comme Qu'est-ce que Mais comment? Comment ça marche, dans la pratique? P>
est-il juste appliqué par le compilateur (par exemple, si vous essayez de remplacer une méthode scellée, elle échouera avec une erreur de compilation) ou par le CLR (par exemple, lorsque vous essayez la méthode de remplacement, le CLR se lancent), ou par les deux ?
Y a-t-il un moyen légal de "supprimer", contournant, ce Mise à jour forte>: J'ai probablement trouvé une façon (voir ma propre réponse) mais je ne suis pas sûr de tout cela est légal, soutenu, standard ... Donc j'ai posté une autre question sur ce nouveau (mais lié) problème ici p>
Je suis ouvert aux commentaires et, bien sûr, des moyens alternatifs (s'ils existent!) Pour le faire. P> finale virtuelle code>. p>
final code> signifie dans ce contexte? Je suppose que cela signifie "Cette méthode ne peut pas être remplacée", alors même si cette méthode a une fente dans la table virtuelle, cette fente ne peut pas être écrasée par une méthode dans une classe dérivée. p>
final code>, c'est-à-dire d'écrire une classe dérivée qui remplace cette méthode? P>
3 Réponses :
Ceci est pour les méthodes provenant d'une interface. C'est un détail de mise en œuvre. Si une classe implémente une interface, la méthode de l'interface est marquée comme Considérez l'exemple suivant: p> de: CLR via C # (Jeffrey Richter) P> Le compilateur C # nécessite une méthode qui implémente une interface
La signature de méthode soit marquée comme publique. le CLR nécessite que
La méthode d'interface soit marquée comme virtuelle. Si vous ne marquez pas explicitement
la méthode comme virtuelle dans votre code source, le compilateur marque le
méthode comme virtuelle et scellée; strong> cela empêche une classe dérivée de
remplacer la méthode d'interface. Si vous marquez explicitement la méthode comme
virtuel, le compilateur marque la méthode comme virtuelle (et le laisse
non scellé); Cela permet à une classe dérivée de remplacer l'interface
Méthode. P>
blockQuote> p> virtuel code>, c'est-à-dire pour le comportement polymorphique (une place dans la table virtuelle (V> (V>). Mais il est également marqué comme
final code> (scellé) em> de sorte que les autres classes d'enfants implémentant la classe de base ne peuvent pas remplacer cette méthode particulière.
Il serait marqué comme final virtuel code> si vous implémentez explicitement la méthode d'interface également.
@HamleThakobyan, oui, il sera marqué comme final virtuel code> en cas de mise en oeuvre explicite également, tout le point est d'empêcher les classes dérivées de
soméclass code> pour remplacer cette méthode particulière et atteindre polymorphisme en même temps
Merci pour votre réponse, mais je posais une chose légèrement différente: comment ça marche, dans la pratique?
Que signifie final dans ce contexte? Je suppose que cela signifie "Cette méthode ne peut pas être remplacée", alors même si cette méthode a une fente dans la table virtuelle, cette fente ne peut pas être écrasée par une méthode dans une classe dérivée. p>
Oui. C'est aussi l'équivalent du mot-clé C # scellé code>, donc par exemple: p>
xxx pré> devient: p>
xxx pré >
virtuel code> concerne le mot clé C #
virtuel code> mais aussi à toute autre méthode virtuelle. Cela inclut
remplacement code> ainsi que toute implémentation de l'interface. En particulier pendant que vous ne pouvez pas définir une méthode comme
scellé virtuel code> en C # (car ce serait inutile, vous devriez donc décider de ce que vous voulez faire), vous pouvez en CIL, et cela se fait dans Quelques implémentations d'interface. P>
à la perspective C # Il existe trois façons de mettre en œuvre une méthode d'interface ou une propriété: p>
- non virtuel. LI>
- virtuel (donc les classes dérivées peuvent le remplacer). Li>
- Mise en œuvre explicite. LI> ol>
à la perspective CIL Tout ce sont
virtuel code> car ils utilisent tous le mécanisme de méthode virtuelle. Les premier et troisième sont également
final code>. P>
(considérez que nous pouvons ignorer le mécanisme de sur-conduit et utiliser
appel code> en CIL pour appeler une méthode pour appeler une méthode Il est défini dans une classe, mais nous devons utiliser
Callvirt code> avec une interface car nous ne savons pas quelle classe nous appelons, donc il doit y avoir une recherche). P>
est-il juste appliqué par le compilateur (par exemple, si vous essayez de remplacer une méthode scellée, elle échouera avec une erreur de compilation) ou par le CLR (par exemple, lorsque vous essayez la méthode de remplacement, le CLR se lancent), ou par les deux ? p> blockquote>
Les deux. p>
Le compilateur C # ne vous permettra pas de remplacer une méthode scellée: p>
xxx pré> Ceci refuse de compiler avec le compilateur Erreur CS0239: "'Test1.Tostring ()' ne peut pas remplacer les éléments hérités de l'élément" Test.Tostring () "car il est scellé". P>
Mais si vous le forcez en écrivant le CIL vous-même: P >
xxx pré> alors si vous appelez
Nouveau test (). Tostring () code> Il renvoie
"A" code> comme vous l'attendez, mais Si vous appelez
nouveau test1 (). TOSTRING () CODE> Vous obtenez une erreur d'exécution: P>
System.TypeLoadException : Declaration referenced in a method implementation cannot be a final method. Type: 'TestAssembly.Test2'. Assembly: 'TestAssembly, Version=1.0.0.1, Culture=neutral, PublicKeyToken=null'.
Merci Jon, j'ai atteint les mêmes conclusions (j'écessais aussi avec elle); votre exemple et votre mien sont très similaires. Souhaitez-vous commenter mon dernier point cependant? Remplacer avec un nom différent?
Je veux dire votre seule option si vous avez vraiment besoin de remplacer est de faire une nouvelle version de la classe que vous souhaitez remplacer (ce qui est strictement un changement de rupture, bien que seuls de rares cas ne soient affectés négativement). Si ce n'est pas votre code, vous n'avez pas de chance.
Oh, attendez. Vous voulez dire explicitement dire que Y remplace X. Cela fonctionne, mais la chaîne de noms est différente pour la prochaine classe dérivée. Je suppose que cela pourrait appeler un nouveau code> x cependant, qui pourrait être remplacé à son tour.
Changer exactement le nom (:: x2 Remplacements :: x), disons qu'il remplace la méthode de la classe de base (base :: x) et la "finale" de la classe intermédiaire n'a plus d'importance. Ensuite, dans la même classe, définissez un neuf code> x qui appelle x2. Mais ça a l'air ... mal. Ou est-ce quelque chose de légal?
Je devrais probablement poster une question différente
Je vais essayer de répondre à ma propre question avec quelques expériences que j'ai faites, car je voulais vraiment comprendre comment cela fonctionne dans la pratique em> (oui, même s'il s'agit d'un détail de mise en œuvre). J'ai écrit une classe dans IL, nommée C2, qui étend une classe C # nommée C1. La méthode qu'elle remplace, M1, est écrite en IL comme finale virtuelle p> ceci apparaît dans iLspy comme p> Visual Studio et CSC le voient correctement comme M1 () et l'appelleront correctement (essayé dans le débogueur). P> Maintenant, c'est ce que ma question était sur: cela devrait être la dernière méthode de la chaîne , mais qui dit cela? p> J'ai écrit une classe dérivée C3, qui tente de remplacer la méthode à nouveau. p> Il assemble avec ilasme, et produit une DLL.
Dans ILSPY: P> .class public auto ansi beforefieldinit N.C3
extends N.C2
{
.method private hidebysig virtual final
instance object M1() cil managed
{
.override N.C1::M1
Presque presque méchant la mise en œuvre finale, plus de chances de remplacer. Similaire à
scellé code> en C #.
Il est destiné au vérificateur i>, la partie de la gigue qui valide le MSIL. Questions aux cours avec des méthodes virtuelles, ils sont très faciles à pirater. La mise en œuvre est simple, si quelqu'un ticks il et dérive de la classe pour remplacer la méthode, le vérificateur y crie et met un arrêt à celui-ci. La langue C # a été conçue pour ne jamais se tromper, mais que vous pourriez pirater en utilisant un faux assemblage de référence.