Quand faut-il utiliser un mot-clé dynamique en c # 4.0?
Dynamic doit être utilisé uniquement lorsqu'il n'est pas utilisé, il est douloureux. Comme dans les bibliothèques MS Office. Dans tous les autres cas, il convient de l'éviter car la vérification du type de compilation est bénéfique. Voici la bonne situation d'utilisation de Dynamic.
Que dis-tu de ça? Quelque chose que je cherchais et que je me demandais pourquoi il était si difficile de se passer de «dynamique».
interface ISomeData {}
class SomeActualData : ISomeData {}
class SomeOtherData : ISomeData {}
interface ISomeInterface
{
void DoSomething(ISomeData data);
}
class SomeImplementation : ISomeInterface
{
public void DoSomething(ISomeData data)
{
dynamic specificData = data;
HandleThis( specificData );
}
private void HandleThis(SomeActualData data)
{ /* ... */ }
private void HandleThis(SomeOtherData data)
{ /* ... */ }
}
Vous devez juste peut-être attraper l'exception Runtime et gérer ce que vous voulez si vous n'avez pas de méthode surchargée prenant le type concret.
L'équivalent de ne pas utiliser dynamic
sera:
public void DoSomething(ISomeData data)
{
if(data is SomeActualData)
HandleThis( (SomeActualData) data);
else if(data is SomeOtherData)
HandleThis( (SomeOtherData) data);
...
else
throw new SomeRuntimeException();
}
Comme décrit dans ici dynamic peut faciliter l'utilisation de bibliothèques externes mal conçues: Microsoft fournit l'exemple de Microsoft.Office.Interop.Excel Assembly . Et avec dynamic, vous pouvez éviter beaucoup de problèmes, casting explicite lors de l'utilisation de cet assemblage.
De plus, contrairement à @ user2415376, ce n'est certainement pas une façon de gérer les interfaces, car nous avons déjà implémenté Polymorphism dès les premiers jours du langage!
Vous pouvez utiliser
ISomeData specificData = data;
au lieu de
dynamic specificData = data;
De plus, cela vous évitera de transmettre un type d'objet de données incorrect.
Consultez cet article de blog qui parle de mots-clés dynamiques en c #. Voici le Gist:
Le mot-clé dynamic est puissant, il est irremplaçable lorsqu'il est utilisé avec des langages dynamiques, mais il peut également être utilisé dans des situations délicates lors de la conception de code lorsqu'un objet statiquement typé ne suffira tout simplement pas.
Considérez les inconvénients:
Il n'y a pas de vérification de type à la compilation, cela signifie que si vous avez une confiance totale dans vos tests unitaires (toux), vous courez un risque.
Le mot-clé dynamic utilise plus de cycles de processeur que votre code à l'ancienne typé de manière statique en raison de la surcharge d'exécution supplémentaire. Si les performances sont importantes pour votre projet (normalement), n'utilisez pas Dynamic.
Les erreurs courantes incluent le renvoi de types anonymes enveloppés dans le mot clé dynamic dans des méthodes publiques. Les types anonymes sont spécifiques à un assemblage, les renvoyer à travers Assembly (via les méthodes publiques) génèreront une erreur, même si de simples tests l’a détecté. Vous disposez maintenant d’une méthode publique que vous pouvez utiliser uniquement à partir d’endroits spécifiques. .
C'est une pente glissante, les développeurs inexpérimentés désirant écrire quelque chose de nouveau et essayant de leur mieux pour éviter davantage de classes (cela ne se limite pas nécessairement à l'inexpérimenté) commenceront à utiliser dynamique de plus en plus s'ils le voient dans le code, habituellement je ferais un code analyse d'analyse pour dynamique/l'ajouter à la révision du code.
C'est certainement une mauvaise idée d'utiliser dynamique dans tous les cas où il peut être utilisé. En effet, vos programmes perdront les avantages de la vérification au moment de la compilation et seront beaucoup plus lents.
Je voudrais copier un extrait de l'article de projet de code, qui définit ce qui suit:
Pourquoi utiliser dynamique?
Dans le monde statiquement typé, dynamique donne beaucoup de corde aux développeurs se pendre avec. Lorsqu'il s'agit d'objets dont les types peuvent être connu au moment de la compilation, évitez le mot-clé dynamique. frais. Un peu plus tôt, j’ai dit que ma réaction initiale était négative, alors quoi changé d'avis? Pour citer Margret Attwood, le contexte est tout. Quand statiquement en tapant, dynamique n'a pas de sens. Si vous êtes s’agissant d’un type inconnu ou dynamique, il est souvent nécessaire de communiquer avec elle par la réflexion. Code réfléchissant n'est pas facile à lu, et a tous les pièges du type dynamique ci-dessus. Dans ce contexte, la dynamique a beaucoup de sens. [Plus]
Certaines des caractéristiques du mot clé dynamique sont les suivantes:
par exemple.,
dynamic str;
str=”I am a string”; //Works fine and compiles
str=2; //Works fine and compiles
Les erreurs sont interceptées au moment de l'exécution
Intellisense n'est pas disponible car le type et ses méthodes et propriétés associées ne peuvent être connus qu'au moment de l'exécution. [ https://www.codeproject.com/Tips/460614/Difference-between-var-and-dynamic-in-Csharp]
Voici un cas récent dans lequel utiliser dynamic
était une solution simple.
J'avais porté du code de VB6 en C #. Ce code porté devait encore appeler d'autres méthodes sur des objets VB6 via COM interop.
Les classes appelées ressemblaient à ceci:
class A
{
void Foo() {...}
}
class B
{
void Foo() {...}
}
(c’est-à-dire que c’est ainsi que les classes de VB6 avaient l’apparence de C # via l’interopérabilité COM; c’est-à-dire le wrapper COM-callable qui était généré automatiquement).
Étant donné que A et B sont indépendants l'un de l'autre, vous ne pouvez pas les utiliser l'un pour l'autre et ils n'ont pas de classe de base commune (COM ne prend pas en charge le fait que AFAIK et VB6 ne le faisaient certainement pas. Et ils n'ont pas implémenté une interface commune - voir ci-dessous).
Le code VB6 d'origine qui a été porté fait ceci:
' Obj must be either an A or a B
Sub Bar(Obj As Object)
Call Obj.Foo()
End Sub
Maintenant, dans VB6, vous pouvez transmettre des éléments sous la forme Object
et le moteur d'exécution déterminera si ces objets ont la méthode Foo()
ou non. Mais en C #, une traduction littérale serait:
// Obj must be either an A or a B
void Bar(object Obj)
{
Obj.Foo();
}
Ce qui ne fonctionnera pas. Il ne compilera pas car object
ne dispose pas d'une méthode appelée "Foo", et C # étant typé, ne le permettra pas.
Donc, le simple "correctif" consistait à utiliser dynamic
, comme ceci:
// Obj must be either an A or a B
void Bar(dynamic Obj)
{
Obj.Foo();
}
Cela retarde la sécurité du type jusqu'à l'exécution, mais si vous l'avez fait correctement, cela fonctionne parfaitement.
Je n'approuverais pas ceci pour le nouveau code, mais dans cette situation (qui selon moi n'est pas rare à en juger par les autres réponses ici), c'était précieux.
Alternatives envisagées:
Utiliser la réflexion pour appeler Foo (). Cela fonctionnerait probablement, mais avec plus d'effort et moins lisible.
La modification de la bibliothèque VB6 n'était pas à l'ordre du jour ici, mais il pourrait peut-être exister une approche pour définir A et B en termes d'interface commune, que VB6 et COM prendraient en charge. Mais utiliser dynamique était beaucoup plus facile.
Remarque: cela s’avérera probablement comme une solution temporaire. Finalement, si le code VB6 restant est transféré, une structure de classe appropriée peut être utilisée et la vérification statique de la compilation remplace l'utilisation de dynamic
. J'admets qu'un avenir aussi prometteur m'a conforté dans l'utilisation de cette approche, qui pourrait comporter certains risques en matière de maintenance.