70

When should one use dynamic keyword in c# 4.0?.......Any good example with dynamic keyword in c# 4.0 that explains its usage....

ACP
  • 34,682
  • 100
  • 231
  • 371

8 Answers8

50

Dynamic should be used only when not using it is painful. Like in MS Office libraries. In all other cases it should be avoided as compile type checking is beneficial. Following are the good situation of using dynamic.

  1. Calling javascript method from Silverlight.
  2. COM interop.
  3. Maybe reading Xml, Json without creating custom classes.
Amitabh
  • 59,111
  • 42
  • 110
  • 159
  • 9
    I like how you put "Maybe" for number 3. I would argue this is a _weak_ "maybe" because usually an investment in defining reusable classes for business data structures pays off in the long term. So the "maybe" should perhaps be reserved for when you are rapidly prototyping a product and either don't have the time or are too lazy to define reusable custom business data types. – nothingisnecessary Nov 23 '16 at 20:02
  • I added below a specific COM interop example https://stackoverflow.com/a/50154066/3195477 – StayOnTarget May 03 '18 at 11:33
18

How about this? Something I've been looking for and was wondering why it was so hard to do without 'dynamic'.

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)
    { /* ... */ }

}

You just have to maybe catch for the Runtime exception and handle how you want if you do not have an overloaded method that takes the concrete type.

Equivalent of not using dynamic will be:

    public void DoSomething(ISomeData data)
    {
        if(data is SomeActualData)
          HandleThis( (SomeActualData) data);
        else if(data is SomeOtherData)
          HandleThis( (SomeOtherData) data);
        ...
        else
         throw new SomeRuntimeException();
    }
Ashkan S
  • 10,464
  • 6
  • 51
  • 80
user2415376
  • 3,440
  • 2
  • 16
  • 13
  • I've been trying to do something like this for a few days, leaving it and coming back to it. This would work very well. So yes this, to me at least, seems very hard to do without `dynamic`. – KDecker Aug 31 '15 at 12:40
  • 16
    OMG! use ISomeData specificData = data; instead of dynamic! Why would you use dynamic for such a simple task – Ashkan S Jan 23 '17 at 09:02
  • 2
    And what if ISomeData comes from another library and you can't add anything in it's source ? Or maybe you want to implement visitor pattern, to be able to add dynamically behavior to those objects ? – gor Feb 18 '17 at 10:48
  • @kan your equivalent is not equivalent at all! you just need to call HandleThis( specificData ); without the casting it. – Ashkan S Mar 27 '18 at 11:47
  • Wow.. didn't expect this post to get this much attention. :) But ya.. polymorphism isn't at play here. In order for that to work, you'd have to edit the ISomeInterface interface and add an entry for each implementation of ISomeData. Have you tried running this code and testing the polymorph idea? There is no way for the code inside SomeImplementation to know what to call via polymorphism. So what this does, is let you code some rule implementations maybe, where the rules engine might get updates as new structures come about. – user2415376 Mar 28 '18 at 21:13
  • My goal was not to post "HEY GOOD WAY TO USE!" but just simply a usage. I strive not to use 'dynamic', only used it this 1 time, maybe 1 other somewhere. And I wrapped a bunch of try/catch around it in case it failed. It was not my desire to use it; it came out of necessity. – user2415376 Mar 28 '18 at 21:20
  • @AshkanSirous How then would you code this? And mind you, clearly this would not be a green field situation, but that there are other limitations in the code base at stake. – user2415376 Mar 28 '18 at 21:27
  • @user2415376 thanks for elaboration. I understand what you mean and I really liked it. Thanks a lot – Ashkan S Apr 09 '18 at 08:06
  • Breaks [Liskov Substitution Principle](https://en.wikipedia.org/wiki/Liskov_substitution_principle) – Jansky May 09 '18 at 08:33
  • @user2415376 how can we differ your solution from using **dynamic** into using **var**? – Andrés Quiroz Valdovinos Apr 07 '20 at 18:13
  • To handle runtime exceptions due to any missing overloaded methods, you could add an additional "private void HandleThis(object data)" as a catch all. – Ε Г И І И О Feb 22 '23 at 08:47
8

As described in here dynamics can make poorly-designed external libraries easier to use: Microsoft provides the example of the Microsoft.Office.Interop.Excel assembly. And With dynamic, you can avoid a lot of annoying, explicit casting when using this assembly.

Also, In opposition to @user2415376 ,It is definitely not a way to handle Interfaces since we already have Polymorphism implemented from the beginning days of the language!
You can use

  ISomeData specificData = data;

instead of

dynamic specificData = data;

Plus it will make sure that you do not pass a wrong type of data object instead.

Ashkan S
  • 10,464
  • 6
  • 51
  • 80
  • 1
    I've added some clarification to @user2415376 answer what exactly happens when `dynamic` is used. Your suggestion to use polymorphism is incorrect. – kan Mar 21 '18 at 13:23
  • @kan your understanding of polymorphism is wrong, therefore your clarification is also wrong. The "HandleThis" method should be implemented with the base class or the interface as the input. you have simply written a code that is not doing anything – Ashkan S Mar 27 '18 at 11:50
  • 1
    Nothing to do with polymorphism here, it is not applicable in this scenario. When `specificData` is of type `ISomeData` then code will not compile as compiler could not pick `HandleThis` method overloads. When `specificData` is of type `dynamic` - the compiler does nothing and overload is picked by run-time type. In other words - `dynamic` allows implementing https://en.wikipedia.org/wiki/Dynamic_dispatch too, not relying on polymorphism. – kan Mar 28 '18 at 14:31
  • 1
    This is another example of the code. Try to use polymorphism here: https://dotnetfiddle.net/Da9gIC – kan Mar 28 '18 at 15:01
  • Referring to my answer, with my comment, it is not polymorphism.. Not saying I'm using 'dynamic' all over.. in fact the 1 or maybe 2 times I've ever used it, I posted it here because it seemed odd to me.. but I was in a situation that I could not get out without it or doing some big heavy lifting in the rest of the code. – user2415376 Mar 28 '18 at 21:14
  • @kan Thanks a lot for the example. It helped me to understand what problem you are addressing and more interestingly I've just used it in a code :D so thank you a lot – Ashkan S Apr 09 '18 at 08:07
  • @AshkanSirous Nice, thanks. I suggest you undo your edit on user2415376's answer to add back my remark then. BTW, this is quite heavy weapon, so do not use this ligthly on any occasion. – kan Apr 09 '18 at 08:54
  • @kan I understand that :D Also I've added a try catch around it, since we don't have many of compile time validations. – Ashkan S Apr 09 '18 at 08:59
5

Check this blog post which talks about dynamic keywords in c#. Here is the gist:

The dynamic keyword is powerful indeed, it is irreplaceable when used with dynamic languages but can also be used for tricky situations while designing code where a statically typed object simply will not do.

Consider the drawbacks:

  1. There is no compile-time type checking, this means that unless you have 100% confidence in your unit tests (cough) you are running a risk.

  2. The dynamic keyword uses more CPU cycles than your old fashioned statically typed code due to the additional runtime overhead, if performance is important to your project (it normally is) don’t use dynamic.

  3. Common mistakes include returning anonymous types wrapped in the dynamic keyword in public methods. Anonymous types are specific to an assembly, returning them across assembly (via the public methods) will throw an error, even though simple testing will catch this, you now have a public method which you can use only from specific places and that’s just bad design.

  4. It’s a slippery slope, inexperienced developers itching to write something new and trying their best to avoid more classes (this is not necessarily limited to the inexperienced) will start using dynamic more and more if they see it in code, usually I would do a code analysis check for dynamic / add it in code review.

StayOnTarget
  • 11,743
  • 10
  • 52
  • 81
Sumit Maingi
  • 2,173
  • 3
  • 24
  • 44
2

Here is a recent case in which using dynamic was a straightforward solution. This is essentially 'duck typing' in a COM interop scenario.

I had ported some code from VB6 into C#. This ported code still needed to call other methods on VB6 objects via COM interop.

The classes needing to be called looked like this:

class A
{
    void Foo() {...}
}

class B
{
    void Foo() {...}
}

(i.e., this would be the way the VB6 classes looked in C# via COM interop.

Since A and B are independent of each other you can't cast one to the other, and they have no common base class (COM doesn't support that AFAIK and VB6 certainly didn't. And they did not implement a common interface - see below).

The original VB6 code which was ported did this:

' Obj must be either an A or a B 
Sub Bar(Obj As Object) 
    Call Obj.Foo()
End Sub

Now in VB6 you can pass things around as Object and the runtime will figure out if those objects have method Foo() or not. But in C# a literal translation would be:

// Obj must be either an A or a B 
void Bar(object Obj) 
{
    Obj.Foo();
}

Which will NOT work. It won't compile because object does not have a method called "Foo", and C# being typesafe won't allow this.

So the simple "fix" was to use dynamic, like this:

// Obj must be either an A or a B 
void Bar(dynamic Obj) 
{
    Obj.Foo();
}

This defers type safety until runtime, but assuming you've done it right works just fine.

I wouldn't endorse this for new code, but in this situation (which I think is not uncommon judging from other answers here) it was valuable.

Alternatives considered:

  • Using reflection to call Foo(). Probably would work, but more effort and less readable.

  • Modifying the VB6 library wasn't on the table here, but maybe there could be an approach to define A and B in terms of a common interface, which VB6 and COM would support. But using dynamic was much easier.


Note: This probably will turn out to be a temporary solution. Eventually if the remaining VB6 code is ported over then a proper class structure can be used.

StayOnTarget
  • 11,743
  • 10
  • 52
  • 81
1

I will like to copy an excerpt from the code project post, which define that :

Why use dynamic?

In the statically typed world, dynamic gives developers a lot of rope to hang themselves with. When dealing with objects whose types can be known at compile time, you should avoid the dynamic keyword at all costs. Earlier, I said that my initial reaction was negative, so what changed my mind? To quote Margret Attwood, context is all. When statically typing, dynamic doesn't make a stitch of sense. If you are dealing with an unknown or dynamic type, it is often necessary to communicate with it through Reflection. Reflective code is not easy to read, and has all the pitfalls of the dynamic type above. In this context, dynamic makes a lot of sense.[More]

While Some of the characteristics of Dynamic keyword are:

  1. Dynamically typed - This means the type of variable declared is decided by the compiler at runtime time.
  2. No need to initialize at the time of declaration.

e.g.,

dynamic str; 

str=”I am a string”; //Works fine and compiles

str=2; //Works fine and compiles
  1. Errors are caught at runtime

  2. Intellisense is not available since the type and its related methods and properties can be known at run time only. [https://www.codeproject.com/Tips/460614/Difference-between-var-and-dynamic-in-Csharp]

Muhammad Faizan Khan
  • 10,013
  • 18
  • 97
  • 186
0

It is definitely a bad idea to use dynamic in all cases where it can be used. This is because your programs will lose the benefits of compile-time checking and they will also be much slower.

Happy
  • 21
  • 7
0

Mostly dynamic is a bad practice to use so I avoid It, but I find It very useful in some scenarios:

1.) Your application saves/deletes/updates some stuff in database or gets data from It. So you'll probably end with 4 methods for save/delete/update/get data. But not needed - construct a simple stored procedure in database that can do all those things (not so hard), and do same in your code. By using dynamic you can return multiple results from same method, like bool for save/delete/update and collection for retrieving data (+ null when error appears). That saves me tons of code lines.

2.) Sometimes I cant' avoid using reflection and generics aren't possible or not needed. So I use dynamic instead, because of It's better performance than reflection.

LuckyLuke82
  • 586
  • 1
  • 18
  • 58