Il est utile lorsque vous travaillez avec COM ou des langages typés dynamiquement. Par exemple, si vous utilisez lua ou python pour écrire votre langage, il est très pratique d'appeler simplement le code de script comme s'il s'agissait de code normal.
Le mot-clé dynamique est nouveau dans C # 4.0 et est utilisé pour indiquer au compilateur que le type d'une variable peut changer ou qu'il n'est pas connu avant l'exécution. Considérez-le comme étant capable d'interagir avec un objet sans avoir à le lancer.
dynamic cust =GetCustomer();
cust.FirstName="foo";// works as expected
cust.Process();// works as expected
cust.MissingMethod();// No method found!
Notez que nous n'avons pas eu besoin de lancer ou de déclarer cust en tant que client de type. Parce que nous l'avons déclaré dynamique, le runtime prend le relais, puis recherche et définit la propriété FirstName pour nous. Maintenant, bien sûr, lorsque vous utilisez une variable dynamique, vous abandonnez la vérification du type de compilateur. Cela signifie que l'appel cust.MissingMethod () sera compilé et n'échouera pas jusqu'à l'exécution. Le résultat de cette opération est une RuntimeBinderException car MissingMethod n'est pas défini sur la classe Customer.
L'exemple ci-dessus montre comment la dynamique fonctionne lors de l'appel de méthodes et de propriétés. Une autre fonctionnalité puissante (et potentiellement dangereuse) est la possibilité de réutiliser des variables pour différents types de données. Je suis sûr que les programmeurs Python, Ruby et Perl peuvent penser à un million de façons de tirer parti de cela, mais j'utilise C # depuis si longtemps que cela me semble "mal".
dynamic foo =123;
foo ="bar";
OK, donc vous n'écrirez probablement pas très souvent du code comme celui-ci. Il peut cependant arriver que la réutilisation de variables puisse être utile ou nettoyer un morceau de code hérité sale. Un cas simple que je rencontre souvent est de devoir constamment convertir entre décimal et double.
decimal foo =GetDecimalValue();
foo = foo /2.5;// Does not compile
foo =Math.Sqrt(foo);// Does not compilestring bar = foo.ToString("c");
La deuxième ligne ne compile pas car 2.5 est tapé comme un double et la ligne 3 ne compile pas car Math.Sqrt attend un double. Évidemment, tout ce que vous avez à faire est de convertir et / ou de changer votre type de variable, mais il peut y avoir des situations où la dynamique a du sens à utiliser.
dynamic foo =GetDecimalValue();// still returns a decimal
foo = foo /2.5;// The runtime takes care of this for us
foo =Math.Sqrt(foo);// Again, the DLR works its magicstring bar = foo.ToString("c");
Personnellement, je n'aime pas l'idée d'utiliser l' dynamicin en c # pour résoudre des problèmes qui peuvent être résolus (peut-être même mieux) par des fonctionnalités standard de c # et du typage statique, ou tout au plus avec l'inférence de type ( var). dynamicdoit seulement être utilisé en ce qui concerne les problèmes avec le DLR Interopérabilité. Si vous écrivez du code dans un langage typé statique, comme c # est, faites-le et n'émulez pas un langage dynamique. C'est juste moche.
Philip Daubmeier
40
Si vous faites un usage dynamicintensif des variables dans votre code où vous n'en avez pas besoin (comme dans votre exemple avec le squareroot), vous abandonnez la vérification des erreurs de temps de compilation; au lieu de cela, vous obtenez maintenant des erreurs d'exécution possibles.
Philip Daubmeier
33
Généralement bien, mais quelques erreurs mineures. Premièrement, il n'est pas correct de dire que dynamique signifie que le type de la variable peut changer. La variable en question est de type "dynamique" (du point de vue du langage C #; du point de vue du CLR la variable est de type objet). Le type d'une variable ne change jamais . Le type d'exécution de la valeur d'une variable peut être n'importe quel type compatible avec le type de la variable. (Ou dans le cas des types de référence, il peut être nul.)
Eric Lippert
15
Concernant votre deuxième point: C # avait déjà la fonction de "créer une variable dans laquelle vous pouvez mettre n'importe quoi" - vous pouvez toujours créer une variable de type objet. La chose intéressante à propos de la dynamique est ce que vous signalez dans votre premier paragraphe: la dynamique est presque identique à l'objet, sauf que l'analyse sémantique est différée jusqu'à l'exécution, et l'analyse sémantique est effectuée sur le type d'exécution de l'expression. (Surtout. Il y a quelques exceptions.)
Eric Lippert
18
J'ai dépensé un point de vote négatif à ce sujet, principalement parce qu'il préconise implicitement l'utilisation du mot-clé pour un usage général. Il a un objectif spécifiquement ciblé (décrit parfaitement dans la réponse de Lasses) et bien que cette réponse soit -techniquement- correcte, elle est susceptible d'induire les développeurs en erreur.
Eight-Bit Guru
211
le dynamic mot-clé a été ajouté, ainsi que de nombreuses autres nouvelles fonctionnalités de C # 4.0, pour simplifier la conversation avec du code qui vit ou provient d'autres runtimes et qui possède différentes API.
Prenons un exemple.
Si vous avez un objet COM, comme le Word.Application objet, et que vous souhaitez ouvrir un document, la méthode pour le faire est fournie avec pas moins de 15 paramètres, dont la plupart sont facultatifs.
Pour appeler cette méthode, vous auriez besoin de quelque chose comme ça (je simplifie, ce n'est pas du code réel):
Notez tous ces arguments? Vous devez passer ceux-ci car C # avant la version 4.0 n'avait pas de notion d'arguments optionnels. Dans C # 4.0, les API COM ont été rendues plus faciles à utiliser en introduisant:
Voyez à quel point il semble plus facile, à quel point il devient plus lisible?
Brisons cela:
named argument, can skip the rest
|
v
wordApplication.Documents.Open(@"C:\Test.docx",ReadOnly:true);^^||
notice no ref keyword, can pass
actual parameter values instead
La magie est que le compilateur C # va maintenant injecter le code nécessaire, et travailler avec de nouvelles classes dans le runtime, pour faire presque exactement la même chose que vous faisiez auparavant, mais la syntaxe vous a été cachée, maintenant vous pouvez vous concentrer sur le quoi , et pas tant sur le comment . Anders Hejlsberg aime dire que vous devez invoquer différentes "incantations", ce qui est une sorte de jeu de mots sur la magie du tout, où vous devez généralement agiter vos mains et dire des mots magiques dans le bon ordre. pour lancer un certain type de sort. L'ancienne façon API de parler aux objets COM était beaucoup de cela, vous aviez besoin de sauter à travers beaucoup de cerceaux afin d'amadouer le compilateur pour compiler le code pour vous.
Les choses se dégradent encore plus en C # avant la version 4.0 si vous essayez de parler à un objet COM pour lequel vous n'avez pas d'interface ou de classe, tout ce que vous avez est une IDispatchréférence.
Si vous ne savez pas ce que c'est, IDispatchc'est essentiellement une réflexion pour les objets COM. Avec une IDispatchinterface, vous pouvez demander à l'objet "quel est le numéro d'identification de la méthode connue sous le nom de Save", et créer des tableaux d'un certain type contenant les valeurs des arguments, et enfin appeler une Invokeméthode sur l' IDispatchinterface pour appeler la méthode, en passant tous les informations que vous avez réussi à graver ensemble.
La méthode Save ci-dessus pourrait ressembler à ceci (ce n'est certainement pas le bon code):
est fondamentalement juste C # rattraper VB en termes d'expressivité, mais le faire de la bonne façon, en le rendant extensible, et pas seulement pour COM. Bien sûr, cela est également disponible pour VB.NET ou tout autre langage intégré au runtime .NET.
Vous pouvez trouver plus d'informations sur l' IDispatchinterface sur Wikipedia: IDispatch si vous voulez en savoir plus. C'est vraiment des trucs sanglants.
Cependant, que se passe-t-il si vous souhaitez parler à un objet Python? Il existe une API différente de celle utilisée pour les objets COM, et comme les objets Python sont également de nature dynamique, vous devez recourir à la magie de la réflexion pour trouver les bonnes méthodes à appeler, leurs paramètres, etc., mais pas le .NET réflexion, quelque chose écrit pour Python, à peu près comme le code IDispatch ci-dessus, tout à fait différent.
Et pour Ruby? Une API différente encore.
JavaScript? Même accord, API différente pour cela également.
Le mot-clé dynamique se compose de deux choses:
Le nouveau mot-clé en C #, dynamic
Un ensemble de classes d'exécution qui sait comment gérer les différents types d'objets, qui implémentent une API spécifique dont le dynamicmot clé a besoin et mappe les appels à la bonne façon de faire les choses. L'API est même documentée, donc si vous avez des objets provenant d'un runtime non couvert, vous pouvez l'ajouter.
Le dynamicmot clé n'est cependant pas destiné à remplacer tout code existant uniquement en .NET. Bien sûr, vous pouvez le faire, mais il n'a pas été ajouté pour cette raison, et les auteurs du langage de programmation C # avec Anders Hejlsberg à l'avant, ont été catégoriques: ils considèrent toujours le C # comme un langage fortement typé et ne sacrifieront pas ce principe.
Cela signifie que bien que vous puissiez écrire du code comme ceci:
dynamic x =10;dynamic y =3.14;dynamic z ="test";dynamic k =true;dynamic l = x + y * z - k;
et de le faire compiler, il ne s'agissait pas d'une sorte de système de type magic-lets-figure-out-what-you-mean-at-runtime.
L'objectif était de faciliter la conversation avec d'autres types d'objets.
Il y a beaucoup de matériel sur Internet sur le mot-clé, les partisans, les opposants, les discussions, les diatribes, les éloges, etc.
Je vous suggère de commencer avec les liens suivants, puis de google pour en savoir plus:
Il est également utile en dehors de COM pour les API JSON Web où la structure des objets JSON désérialisés n'est pas spécifiée en C #. Par exemple, la méthode Decode de System.Web.Helpers.Json renvoie un objet dynamique .
dumbledad
Un petit mot sur "ils considèrent toujours le C # comme un langage fortement typé": Eric Lippert n'est pas fan de "fortement typé" comme description.
Andrew Keeton
Je ne suis pas d'accord avec lui, mais c'est une question d'opinion, pas une question de fait. "Fortement typé" signifie pour moi que le compilateur sait, au moment de la compilation, quel type est utilisé, et applique ainsi les règles définies autour de ces types. Le fait que vous puissiez opter pour un type dynamique qui reporte la vérification des règles et la liaison à l'exécution ne signifie pas pour moi que la langue est faiblement typée. Je ne compare généralement pas fortement typé à faiblement typé, cependant, je le compare généralement à typé dynamiquement, comme des langages comme Python, où tout est un canard jusqu'à ce qu'il aboie.
Lasse V. Karlsen
Quel est l'intérêt de cette réponse? La moitié concerne les paramètres optionnels et l'interface IDispatch.
Xam
C'est pourquoi a dynamicété ajouté, pour soutenir d'autres écosystèmes sur la façon dont l'invocation de méthodes de réflexion peut être effectuée, ainsi que pour fournir une sorte d'approche de boîte noire aux structures de données avec un moyen documenté d'y parvenir.
Lasse V. Karlsen
29
Je suis surpris que personne n'ait mentionné l' envoi multiple . La façon habituelle de contourner cela est via le modèle de visiteur et ce n'est pas toujours possible, vous vous retrouvez donc avec des ischèques empilés .
Voici donc un exemple concret de ma propre application. Au lieu de faire:
publicstaticMapDtoBaseCreateDto(ChartItem item){if(item isElevationPoint)returnCreateDtoImpl((ElevationPoint)item);if(item isMapPoint)returnCreateDtoImpl((MapPoint)item);if(item isMapPolyline)returnCreateDtoImpl((MapPolyline)item);//other subtypes followthrownewObjectNotFoundException("Counld not find suitable DTO for "+ item.GetType());}
Tu fais:
publicstaticMapDtoBaseCreateDto(ChartItem item){returnCreateDtoImpl(item asdynamic);}privatestaticMapDtoBaseCreateDtoImpl(ChartItem item){thrownewObjectNotFoundException("Counld not find suitable DTO for "+ item.GetType());}privatestaticMapDtoBaseCreateDtoImpl(MapPoint item){returnnewMapPointDto(item);}privatestaticMapDtoBaseCreateDtoImpl(ElevationPoint item){returnnewElevationDto(item);}
Notez que dans le premier cas ElevationPointest une sous-classe de MapPointet s'il n'est pas placé avant,MapPoint il ne sera jamais atteint. Ce n'est pas le cas avec dynamique, car la méthode de correspondance la plus proche sera appelée.
Comme vous pouvez le deviner à partir du code, cette fonctionnalité était utile pendant que j'effectuais la traduction des objets ChartItem vers leurs versions sérialisables. Je ne voulais pas polluer mon code avec les visiteurs et je ne voulais pas non plus polluer mes ChartItemobjets avec des attributs spécifiques de sérialisation inutiles.
Je ne connaissais pas ce cas d'utilisation. Un peu hacky au mieux, cependant. Cela détruira tout analyseur statique.
Kugel
2
@Kugel c'est vrai, mais je n'appellerais pas ça un hack . L'analyse statique est bonne, mais je ne laisserai pas cela m'empêcher d'une solution élégante, où les alternatives sont: violation du principe ouvert-fermé (modèle de visiteur) ou complexité cyclomatique accrue avec un redoutable isempilé les uns sur les autres.
Stelios Adamantidis
4
Eh bien, vous avez la possibilité de faire correspondre les motifs avec C # 7, non?
Kugel
2
Eh bien, les opérateurs sont beaucoup moins chers de cette façon (en évitant la double conversion) et vous obtenez une analyse statique ;-) et des performances.
Kugel
@idbrii s'il vous plaît ne changez pas mes réponses. N'hésitez pas à laisser un commentaire et je clarifierai (si nécessaire) car je suis toujours actif dans cette communauté. Aussi, veuillez ne pas utiliser magic; la magie n'existe pas.
Stelios Adamantidis
11
Il facilite l'interopérabilité des langages typés statiques (CLR) avec les langages dynamiques (python, ruby ...) fonctionnant sur le DLR (runtime de langage dynamique), voir MSDN :
Par exemple, vous pouvez utiliser le code suivant pour incrémenter un compteur en XML en C #.
Et le changement de VM requis pour dynamique rend en fait les langues dynamiques plus faciles.
Dykam
2
@Dykam: Il n'y a aucun changement sur la VM. Le DLR fonctionne très bien jusqu'à .NET 2.0.
Jörg W Mittag
@ Jörg, oui il y a un changement. Le DLR est en partie réécrit parce que la machine virtuelle prend désormais en charge la résolution dynamique.
Dykam
J'étais un peu trop optimiste, les recherches ont montré que les changements n'étaient pas si importants.
Dykam
4
Un exemple d'utilisation:
Vous consommez de nombreuses classes qui ont une propriété commune 'CreationDate':
publicclassContact{// some propertiespublicDateTimeCreationDate{get;set;}}publicclassCompany{// some propertiespublicDateTimeCreationDate{get;set;}}publicclassOpportunity{// some propertiespublicDateTimeCreationDate{get;set;}}
Si vous écrivez une méthode commun qui récupère la valeur de la propriété 'CreationDate', vous devrez utiliser la réflexion:
Il sera principalement utilisé par les victimes RAD et Python pour détruire la qualité du code, IntelliSense et compiler la détection des bogues de temps.
Une réponse cynique mais facilement trop vraie. Je l'ai vu faire simplement pour éviter de déclarer des structures avec pour résultat que le code fonctionne si tout va bien, mais souffle sa pile de manière imprévisible dès que vous déplacez son fromage.
AnthonyVO
Oui, vous verrez cette coupe de coin classique avec de nombreuses autres fonctionnalités linguistiques. Il n'est pas surprenant que vous le voyiez également ici.
Hawkeye4040
1
Il évalue au moment de l'exécution, vous pouvez donc changer le type comme vous le pouvez en JavaScript vers ce que vous voulez. Cela est légitime:
dynamic i =12;
i ="text";
Et vous pouvez donc changer le type selon vos besoins. Utilisez-le en dernier recours; c'est bénéfique, mais j'ai entendu beaucoup de choses se passer dans les coulisses en termes d'IL généré et cela peut avoir un prix de performance.
J'hésiterais à dire que c'est "légitime". Il compilera sûrement, donc en tant que tel, c'est du "code légitime" dans le sens où le compilateur le compilera maintenant, et le runtime l'exécutera. Mais je ne voudrais jamais voir ce morceau de code particulier (ou quelque chose qui lui ressemble) dans l'un des codes que je maintiens, ou ce serait une infraction de tir imminent.
Lasse V. Karlsen du
6
Bien sûr, mais cela aurait été "légitime" avec "objet" au lieu de "dynamique". Vous n'avez rien montré d'intéressant sur la dynamique ici.
Eric Lippert
Pour l'objet, vous devez le convertir dans le type approprié, afin d'invoquer réellement l'une de ses méthodes ... vous perdez la signature; vous pouvez demander à votre code d'appeler n'importe quelle méthode sans erreur de compilation, et il génère des erreurs lors de l'exécution. J'étais pressé de taper, désolé de ne pas l'avoir précisé. Et @Lasse, je serais d'accord et je n'utiliserai probablement pas beaucoup la dynamique.
Brian Mains
1
Le cas d'utilisation de dernier recours n'est pas expliqué
denfromufa
1
Le meilleur cas d'utilisation de variables de type «dynamique» pour moi était lorsque, récemment, j'écrivais une couche d'accès aux données dans ADO.NET (à l' aide de SQLDataReader ) et que le code invoquait les procédures stockées héritées déjà écrites. Il existe des centaines de ces procédures stockées héritées contenant la majeure partie de la logique métier. Ma couche d'accès aux données devait retourner une sorte de données structurées à la couche logique métier, basée sur C #, pour effectuer certaines manipulations ( bien qu'il n'y en ait presque pas ). Chaque procédure stockée renvoie un ensemble de données différent ( colonnes de table ). Donc, au lieu de créer des dizaines de classes ou de structures pour contenir les données renvoyées et les transmettre au BLL, j'ai écrit le code ci-dessous qui semble assez élégant et soigné.
publicstaticdynamicGetSomeData(ParameterDTO dto){dynamic result =null;stringSPName="a_legacy_stored_procedure";
using (SqlConnection connection =newSqlConnection(DataConnection.ConnectionString)){SqlCommand command =newSqlCommand(SPName, connection);
command.CommandType=System.Data.CommandType.StoredProcedure;
command.Parameters.Add(newSqlParameter("@empid", dto.EmpID));
command.Parameters.Add(newSqlParameter("@deptid", dto.DeptID));
connection.Open();
using (SqlDataReader reader = command.ExecuteReader()){while(reader.Read()){dynamic row =newExpandoObject();
row.EmpName= reader["EmpFullName"].ToString();
row.DeptName= reader["DeptName"].ToString();
row.AnotherColumn= reader["AnotherColumn"].ToString();
result = row;}}}return result;}
Vous pouvez appeler des langages dynamiques tels que CPython en utilisant pythonnet:
dynamic np = Py.Import("numpy")
Vous pouvez convertir des génériques en leur dynamicappliquant des opérateurs numériques. Cela offre une sécurité de type et évite les limitations des génériques. Il s'agit essentiellement de la saisie de canard:
Un autre cas d'utilisation pour la dynamicsaisie concerne les méthodes virtuelles qui rencontrent un problème de covariance ou de contravariance. Un tel exemple est la fameuse Cloneméthode qui renvoie un objet du même type que l'objet auquel il est appelé. Ce problème n'est pas complètement résolu avec un retour dynamique car il contourne la vérification de type statique, mais au moins vous n'avez pas besoin d'utiliser des conversions laides tout le temps comme lors de l'utilisation de plain object. Autrement dit, les moulages deviennent implicites.
publicclass A
{// attributes and constructor herepublicvirtualdynamicClone(){var clone =new A();// Do more cloning stuff herereturn clone;}}publicclass B : A
{// more attributes and constructor herepublicoverridedynamicClone(){var clone =new B();// Do more cloning stuff herereturn clone;}}publicclassProgram{publicstaticvoidMain(){
A a =new A().Clone();// No cast needed here
B b =new B().Clone();// and here// do more stuff with a and b}}
Réponses:
Le mot-clé dynamique est nouveau dans C # 4.0 et est utilisé pour indiquer au compilateur que le type d'une variable peut changer ou qu'il n'est pas connu avant l'exécution. Considérez-le comme étant capable d'interagir avec un objet sans avoir à le lancer.
Notez que nous n'avons pas eu besoin de lancer ou de déclarer cust en tant que client de type. Parce que nous l'avons déclaré dynamique, le runtime prend le relais, puis recherche et définit la propriété FirstName pour nous. Maintenant, bien sûr, lorsque vous utilisez une variable dynamique, vous abandonnez la vérification du type de compilateur. Cela signifie que l'appel cust.MissingMethod () sera compilé et n'échouera pas jusqu'à l'exécution. Le résultat de cette opération est une RuntimeBinderException car MissingMethod n'est pas défini sur la classe Customer.
L'exemple ci-dessus montre comment la dynamique fonctionne lors de l'appel de méthodes et de propriétés. Une autre fonctionnalité puissante (et potentiellement dangereuse) est la possibilité de réutiliser des variables pour différents types de données. Je suis sûr que les programmeurs Python, Ruby et Perl peuvent penser à un million de façons de tirer parti de cela, mais j'utilise C # depuis si longtemps que cela me semble "mal".
OK, donc vous n'écrirez probablement pas très souvent du code comme celui-ci. Il peut cependant arriver que la réutilisation de variables puisse être utile ou nettoyer un morceau de code hérité sale. Un cas simple que je rencontre souvent est de devoir constamment convertir entre décimal et double.
La deuxième ligne ne compile pas car 2.5 est tapé comme un double et la ligne 3 ne compile pas car Math.Sqrt attend un double. Évidemment, tout ce que vous avez à faire est de convertir et / ou de changer votre type de variable, mais il peut y avoir des situations où la dynamique a du sens à utiliser.
En savoir plus: http://www.codeproject.com/KB/cs/CSharp4Features.aspx
la source
dynamic
in en c # pour résoudre des problèmes qui peuvent être résolus (peut-être même mieux) par des fonctionnalités standard de c # et du typage statique, ou tout au plus avec l'inférence de type (var
).dynamic
doit seulement être utilisé en ce qui concerne les problèmes avec le DLR Interopérabilité. Si vous écrivez du code dans un langage typé statique, comme c # est, faites-le et n'émulez pas un langage dynamique. C'est juste moche.dynamic
intensif des variables dans votre code où vous n'en avez pas besoin (comme dans votre exemple avec le squareroot), vous abandonnez la vérification des erreurs de temps de compilation; au lieu de cela, vous obtenez maintenant des erreurs d'exécution possibles.le
dynamic
mot-clé a été ajouté, ainsi que de nombreuses autres nouvelles fonctionnalités de C # 4.0, pour simplifier la conversation avec du code qui vit ou provient d'autres runtimes et qui possède différentes API.Prenons un exemple.
Si vous avez un objet COM, comme le
Word.Application
objet, et que vous souhaitez ouvrir un document, la méthode pour le faire est fournie avec pas moins de 15 paramètres, dont la plupart sont facultatifs.Pour appeler cette méthode, vous auriez besoin de quelque chose comme ça (je simplifie, ce n'est pas du code réel):
Notez tous ces arguments? Vous devez passer ceux-ci car C # avant la version 4.0 n'avait pas de notion d'arguments optionnels. Dans C # 4.0, les API COM ont été rendues plus faciles à utiliser en introduisant:
ref
facultatif pour les API COMLa nouvelle syntaxe de l'appel ci-dessus serait:
Voyez à quel point il semble plus facile, à quel point il devient plus lisible?
Brisons cela:
La magie est que le compilateur C # va maintenant injecter le code nécessaire, et travailler avec de nouvelles classes dans le runtime, pour faire presque exactement la même chose que vous faisiez auparavant, mais la syntaxe vous a été cachée, maintenant vous pouvez vous concentrer sur le quoi , et pas tant sur le comment . Anders Hejlsberg aime dire que vous devez invoquer différentes "incantations", ce qui est une sorte de jeu de mots sur la magie du tout, où vous devez généralement agiter vos mains et dire des mots magiques dans le bon ordre. pour lancer un certain type de sort. L'ancienne façon API de parler aux objets COM était beaucoup de cela, vous aviez besoin de sauter à travers beaucoup de cerceaux afin d'amadouer le compilateur pour compiler le code pour vous.
Les choses se dégradent encore plus en C # avant la version 4.0 si vous essayez de parler à un objet COM pour lequel vous n'avez pas d'interface ou de classe, tout ce que vous avez est une
IDispatch
référence.Si vous ne savez pas ce que c'est,
IDispatch
c'est essentiellement une réflexion pour les objets COM. Avec uneIDispatch
interface, vous pouvez demander à l'objet "quel est le numéro d'identification de la méthode connue sous le nom de Save", et créer des tableaux d'un certain type contenant les valeurs des arguments, et enfin appeler uneInvoke
méthode sur l'IDispatch
interface pour appeler la méthode, en passant tous les informations que vous avez réussi à graver ensemble.La méthode Save ci-dessus pourrait ressembler à ceci (ce n'est certainement pas le bon code):
Tout cela pour simplement ouvrir un document.
VB avait des arguments et un support optionnels pour la plupart de ces éléments il y a longtemps, donc ce code C #:
est fondamentalement juste C # rattraper VB en termes d'expressivité, mais le faire de la bonne façon, en le rendant extensible, et pas seulement pour COM. Bien sûr, cela est également disponible pour VB.NET ou tout autre langage intégré au runtime .NET.
Vous pouvez trouver plus d'informations sur l'
IDispatch
interface sur Wikipedia: IDispatch si vous voulez en savoir plus. C'est vraiment des trucs sanglants.Cependant, que se passe-t-il si vous souhaitez parler à un objet Python? Il existe une API différente de celle utilisée pour les objets COM, et comme les objets Python sont également de nature dynamique, vous devez recourir à la magie de la réflexion pour trouver les bonnes méthodes à appeler, leurs paramètres, etc., mais pas le .NET réflexion, quelque chose écrit pour Python, à peu près comme le code IDispatch ci-dessus, tout à fait différent.
Et pour Ruby? Une API différente encore.
JavaScript? Même accord, API différente pour cela également.
Le mot-clé dynamique se compose de deux choses:
dynamic
dynamic
mot clé a besoin et mappe les appels à la bonne façon de faire les choses. L'API est même documentée, donc si vous avez des objets provenant d'un runtime non couvert, vous pouvez l'ajouter.Le
dynamic
mot clé n'est cependant pas destiné à remplacer tout code existant uniquement en .NET. Bien sûr, vous pouvez le faire, mais il n'a pas été ajouté pour cette raison, et les auteurs du langage de programmation C # avec Anders Hejlsberg à l'avant, ont été catégoriques: ils considèrent toujours le C # comme un langage fortement typé et ne sacrifieront pas ce principe.Cela signifie que bien que vous puissiez écrire du code comme ceci:
et de le faire compiler, il ne s'agissait pas d'une sorte de système de type magic-lets-figure-out-what-you-mean-at-runtime.
L'objectif était de faciliter la conversation avec d'autres types d'objets.
Il y a beaucoup de matériel sur Internet sur le mot-clé, les partisans, les opposants, les discussions, les diatribes, les éloges, etc.
Je vous suggère de commencer avec les liens suivants, puis de google pour en savoir plus:
la source
dynamic
été ajouté, pour soutenir d'autres écosystèmes sur la façon dont l'invocation de méthodes de réflexion peut être effectuée, ainsi que pour fournir une sorte d'approche de boîte noire aux structures de données avec un moyen documenté d'y parvenir.Je suis surpris que personne n'ait mentionné l' envoi multiple . La façon habituelle de contourner cela est via le modèle de visiteur et ce n'est pas toujours possible, vous vous retrouvez donc avec des
is
chèques empilés .Voici donc un exemple concret de ma propre application. Au lieu de faire:
Tu fais:
Notez que dans le premier cas
ElevationPoint
est une sous-classe deMapPoint
et s'il n'est pas placé avant,MapPoint
il ne sera jamais atteint. Ce n'est pas le cas avec dynamique, car la méthode de correspondance la plus proche sera appelée.Comme vous pouvez le deviner à partir du code, cette fonctionnalité était utile pendant que j'effectuais la traduction des objets ChartItem vers leurs versions sérialisables. Je ne voulais pas polluer mon code avec les visiteurs et je ne voulais pas non plus polluer mes
ChartItem
objets avec des attributs spécifiques de sérialisation inutiles.la source
is
empilé les uns sur les autres.magic
; la magie n'existe pas.Il facilite l'interopérabilité des langages typés statiques (CLR) avec les langages dynamiques (python, ruby ...) fonctionnant sur le DLR (runtime de langage dynamique), voir MSDN :
MSDN répertorie ces avantages:
Voir MSDN pour plus de détails.
la source
Un exemple d'utilisation:
Vous consommez de nombreuses classes qui ont une propriété commune 'CreationDate':
Si vous écrivez une méthode commun qui récupère la valeur de la propriété 'CreationDate', vous devrez utiliser la réflexion:
Avec le concept «dynamique», votre code est beaucoup plus élégant:
la source
Interopérabilité COM. Surtout IUnknown. Il a été spécialement conçu pour cela.
la source
Il sera principalement utilisé par les victimes RAD et Python pour détruire la qualité du code, IntelliSense et compiler la détection des bogues de temps.
la source
Il évalue au moment de l'exécution, vous pouvez donc changer le type comme vous le pouvez en JavaScript vers ce que vous voulez. Cela est légitime:
Et vous pouvez donc changer le type selon vos besoins. Utilisez-le en dernier recours; c'est bénéfique, mais j'ai entendu beaucoup de choses se passer dans les coulisses en termes d'IL généré et cela peut avoir un prix de performance.
la source
Le meilleur cas d'utilisation de variables de type «dynamique» pour moi était lorsque, récemment, j'écrivais une couche d'accès aux données dans ADO.NET (à l' aide de SQLDataReader ) et que le code invoquait les procédures stockées héritées déjà écrites. Il existe des centaines de ces procédures stockées héritées contenant la majeure partie de la logique métier. Ma couche d'accès aux données devait retourner une sorte de données structurées à la couche logique métier, basée sur C #, pour effectuer certaines manipulations ( bien qu'il n'y en ait presque pas ). Chaque procédure stockée renvoie un ensemble de données différent ( colonnes de table ). Donc, au lieu de créer des dizaines de classes ou de structures pour contenir les données renvoyées et les transmettre au BLL, j'ai écrit le code ci-dessous qui semble assez élégant et soigné.
la source
dynamic np = Py.Import("numpy")
dynamic
appliquant des opérateurs numériques. Cela offre une sécurité de type et évite les limitations des génériques. Il s'agit essentiellement de la saisie de canard:T y = x * (dynamic)x
, oùtypeof(x) is T
la source
Un autre cas d'utilisation pour la
dynamic
saisie concerne les méthodes virtuelles qui rencontrent un problème de covariance ou de contravariance. Un tel exemple est la fameuseClone
méthode qui renvoie un objet du même type que l'objet auquel il est appelé. Ce problème n'est pas complètement résolu avec un retour dynamique car il contourne la vérification de type statique, mais au moins vous n'avez pas besoin d'utiliser des conversions laides tout le temps comme lors de l'utilisation de plainobject
. Autrement dit, les moulages deviennent implicites.la source