Problem
The new type ‘dynamic’ was introduced in C# 4.0. All of this sounds great, but how would a coder use it?
Is there a circumstance in which it could come to the rescue?
Asked by Fahad
Solution #1
The dynamic keyword was added to C# 4.0, along with a slew of other new features, to make it easier to communicate with code that exists in or comes from other runtimes and uses different APIs.
Take an example.
If you have a COM object, such as Word.Application, and you wish to open a document, the method to do so has at least 15 parameters, the majority of which are optional.
You’d need something like this to call this method (I’m simplifying; this isn’t actual code):
object missing = System.Reflection.Missing.Value;
object fileName = "C:\\test.docx";
object readOnly = true;
wordApplication.Documents.Open(ref fileName, ref missing, ref readOnly,
ref missing, ref missing, ref missing, ref missing, ref missing,
ref missing, ref missing, ref missing, ref missing, ref missing,
ref missing, ref missing);
Have you taken note of all the counter-arguments? Because C# before version 4.0 didn’t have the concept of optional arguments, you’ll need to pass them. COM APIs have been made easier to work with in C# 4.0 with the addition of:
For the above call, the new syntax would be:
wordApplication.Documents.Open(@"C:\Test.docx", ReadOnly: true);
See how much easier it appears to be, and how much more readable it is?
Let’s break it down:
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
The magic is that the C# compiler will now inject the appropriate code and work with new classes in the runtime to perform essentially exactly the same thing you did before, but without the syntax. Now you can focus on the what, rather than the how. Anders Hejlsberg likes to suggest that you have to use various “incantations,” which is a play on the magic of the whole process, in which you normally have to wave your hand(s) and say some magic words in the appropriate order to get a given type of spell going. There was a lot of that in the old API style of interacting to COM objects; you had to go through a lot of hoops.
When you try to talk to a COM object for which you don’t have an interface or class, all you have is an IDispatch reference in C# before version 4.0, things fall down even worse.
If you’re unfamiliar with IDispatch, it’s essentially COM object reflection. With an IDispatch interface, you may query the object “what is the id number for the Save function?” and then create arrays of a certain type containing the argument values, before calling the method with the information you’ve gathered via an Invoke method on the IDispatch interface.
The Save procedure described above could look like this (this is not the correct code):
string[] methodNames = new[] { "Open" };
Guid IID = ...
int methodId = wordApplication.GetIDsOfNames(IID, methodNames, methodNames.Length, lcid, dispid);
SafeArray args = new SafeArray(new[] { fileName, missing, missing, .... });
wordApplication.Invoke(methodId, ... args, ...);
All of effort just to open a document.
For a long time, VB has optional arguments and support for most of this out of the box, thus this C# code:
wordApplication.Documents.Open(@"C:\Test.docx", ReadOnly: true);
is essentially C# catching up to VB in terms of expressiveness, but in a proper sense, by making it expandable and not just for COM. Naturally, this is also accessible for VB.NET and any other language built on top of the.NET framework.
If you wish to learn more about the IDispatch interface, you may read about it on Wikipedia: IDispatch. It’s quite gruesome.
But what if you wanted to communicate with a Python object? There’s a different API for that than there is for COM objects, and because Python objects are dynamic as well, you’ll need to use reflection magic to find the right methods to call, their parameters, and so on. But not the.NET reflection, but something written specifically for Python, similar to the IDispatch code above but different.
What about Ruby’s situation? It’s still a unique API.
JavaScript? That’s the same deal, but with a different API.
Two elements make up the dynamic keyword:
The dynamic keyword, on the other hand, isn’t intended to replace any existing.NET-only code. Sure, you can do so, but it wasn’t included for that reason, and the C# programming language’s authors, led by Anders Hejlsberg, have been categorical that C# is still a highly typed language, and will not abandon that idea.
This means that, while you can write code that looks like this:
dynamic x = 10;
dynamic y = 3.14;
dynamic z = "test";
dynamic k = true;
dynamic l = x + y * z - k;
It was not intended to be a sort of magic-let’s-figure-out-what-you-meant-at-runtime type of system.
The whole point was to make it easy to communicate with other items.
There’s a lot of information on the keyword on the internet, including proponents, opponents, discussions, rants, compliments, and so on.
I recommend that you start with the following links and then search the internet for more:
Answered by Lasse V. Karlsen
Solution #2
The dynamic keyword is introduced in C# 4.0 and tells the compiler that the type of a variable can change or is unknown until runtime. Consider it like being able to interact with an Object without casting it.
dynamic cust = GetCustomer();
cust.FirstName = "foo"; // works as expected
cust.Process(); // works as expected
cust.MissingMethod(); // No method found!
It’s worth noting that we didn’t have to cast or declare cust as a Customer type. Because it’s dynamic, the runtime takes control and finds and sets the FirstName property for us. When you use a dynamic variable, you are, of course, foregoing compiler type verification. The call cust is what this refers to. Until runtime, MissingMethod() will compile and not fail. Because MissingMethod isn’t defined on the Customer class, this operation throws a RuntimeBinderException.
The preceding example demonstrates how dynamic functions when invoking methods and properties. The ability to reuse variables for different sorts of data is another useful (and potentially harmful) feature. I’m sure Python, Ruby, and Perl programmers can come up with a million ways to use this, but I’ve been using C# for so long that it feels “wrong” to me.
dynamic foo = 123;
foo = "bar";
So, you’re probably not going to be creating code like this very often. However, there are situations when variable reuse might save the day or clean up a sloppy piece of outdated code. One common scenario I encounter is having to convert from decimal and double.
decimal foo = GetDecimalValue();
foo = foo / 2.5; // Does not compile
foo = Math.Sqrt(foo); // Does not compile
string bar = foo.ToString("c");
Because 2.5 is typed as a double, the second line fails to compile, and line 3 fails to compile because Math.Sqrt requires a double. Obviously, all you have to do is cast and/or alter the type of your variable, but there may be times when dynamic is more appropriate.
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 magic
string bar = foo.ToString("c");
More information on this feature can be found at http://www.codeproject.com/KB/cs/CSharp4Features.aspx.
Answered by Pranay Rana
Solution #3
Nobody suggested multiple dispatch, which shocked me. The most common solution to avoid this is to use the Visitor pattern, but this isn’t always possible, thus you wind up with stacked is checks.
So here’s a real-life example of one of my own applications. rather than doing:
public static MapDtoBase CreateDto(ChartItem item)
{
if (item is ElevationPoint) return CreateDtoImpl((ElevationPoint)item);
if (item is MapPoint) return CreateDtoImpl((MapPoint)item);
if (item is MapPolyline) return CreateDtoImpl((MapPolyline)item);
//other subtypes follow
throw new ObjectNotFoundException("Counld not find suitable DTO for " + item.GetType());
}
You do:
public static MapDtoBase CreateDto(ChartItem item)
{
return CreateDtoImpl(item as dynamic);
}
private static MapDtoBase CreateDtoImpl(ChartItem item)
{
throw new ObjectNotFoundException("Counld not find suitable DTO for " + item.GetType());
}
private static MapDtoBase CreateDtoImpl(MapPoint item)
{
return new MapPointDto(item);
}
private static MapDtoBase CreateDtoImpl(ElevationPoint item)
{
return new ElevationDto(item);
}
Note that ElevationPoint is a subclass of MapPoint in the first case, and if it isn’t placed before MapPoint, it will never be reached. This is not the case with dynamic, as the method with the closest match is used.
That capability came in helpful while I was translating ChartItem objects to their serializable variants, as you can see from the code. I didn’t want visitors to contaminate my code, and I didn’t want serialization-specific attributes to pollute my ChartItem objects.
Answered by Stelios Adamantidis
Solution #4
It enables static typed languages (CLR) to communicate with dynamic languages (python, ruby, etc.) running on the DLR (dynamic language runtime); see MSDN:
These benefits are listed in MSDN:
For further information, see MSDN.
Answered by Philip Daubmeier
Solution #5
Use this example:
You use a lot of classes with the ‘CreationDate’ property:
public class Contact
{
// some properties
public DateTime CreationDate { get; set; }
}
public class Company
{
// some properties
public DateTime CreationDate { get; set; }
}
public class Opportunity
{
// some properties
public DateTime CreationDate { get; set; }
}
If you want to obtain the value of the ‘CreationDate’ Property in a common method, you’ll have to use reflection:
static DateTime RetrieveValueOfCreationDate(Object item)
{
return (DateTime)item.GetType().GetProperty("CreationDate").GetValue(item);
}
Your code is significantly more elegant with the ‘dynamic’ concept:
static DateTime RetrieveValueOfCreationDate(dynamic item)
{
return item.CreationDate;
}
Answered by Akli
Post is based on https://stackoverflow.com/questions/2690623/what-is-the-dynamic-type-in-c-sharp-4-0-used-for