views:

1872

answers:

7

The ExpandoObject class being added to .NET 4 allows you to arbitrarily set properties onto an object at runtime.

Are there any advantages to this over using a Dictionary<string,object>, or really even a Hashtable? As far as I can tell, this is nothing but a hash table that you can access with slightly more succinct syntax.

For example, why is this:

dynamic obj = new ExpandoObject();
obj.MyInt = 3;
obj.MyString = "Foo";
Console.WriteLine(obj.MyString);

Really better, or substantially different, than:

var obj = new Dictionary<string, object>();
obj["MyInt"] = 3;
obj["MyString"] = "Foo";

Console.WriteLine(obj["MyString"]);

What real advantages are gained by using ExpandoObject instead of just using an arbitrary dictionary type, other than not being obvious that you're using a type that's going to be determined at runtime.

+2  A: 

It's all about programmer convenience. I can imagine writing quick and dirty programs with this object.

ChaosPandion
+1 Convenience.
J.Hendrix
+4  A: 

One advantage is for binding scenarios. Data grids and property grids will pick up the dynamic properties via the TypeDescriptor system. In addition, WPF data binding will understand dynamic properties, so WPF controls can bind to an ExpandoObject more readily than a dictionary.

Interoperability with dynamic languages, which will be expecting DLR properties rather than dictionary entries, may also be a consideration in some scenarios.

itowlson
+1 Databinding and Interop
Jeroen Pluimers
+1  A: 

Interop with other languages founded on the DLR is #1 reason I can think of. You can't pass them a Dictionary as it's not an IDynamicMetaObjectProvider. Another added benefit is that it implements INotifyPropertyChanged which means in the databinding world of WPF it also has added benefits beyond what Dictionary can provide you.

Drew Marsh
+1  A: 

I think it will have a syntactic benefit, since you'll no longer be "faking" dynamically added properties by using a dictionary.

That, and interop with dynamic languages I would think.

Gurdas Nijor
A: 

The ExpandoObject will also give you IntelliSense hints.

J.Hendrix
J, are you sure about this? The whole point of ExpandoObject is that you would use it with the dynamic keyword to allow the simulated property syntax -- the properties don't exist in the type definition -- and you don't get intellisense on dynamic. You could declare a variable of static type ExpandoObject but intellisense still would show only the static type members, not the dynamic properties.
itowlson
Intellisense will only work with statically defined types...
Gurdas Nijor
No. Sorry. You will _not_ get intellisense on any part assigned dynamically. If I understand correctly, however, you will get the hints for any non-dynamic parts. However, I have not actually played with 4.0 yet so I could be horribly wrong.
J.Hendrix
Actually, forgive me. I think I am horribly wrong... Let me get back to you.
J.Hendrix
It doesn't work.
Reed Copsey
+46  A: 

Since I wrote the MSDN article you are referring to, I guess I have to answer this one.

First, I anticipated this question and that's why I wrote a blog post that shows a more or less real use case for ExpandoObject: Dynamic in C# 4.0: Introducing the ExpandoObject.

Shortly, ExpandoObject can help you create complex hierarchical objects. For example, imagine that you have a dictionary within a dictionary:

Dictionary<String, object> dict = new Dictionary<string, object>();
Dictionary<String, object> address = new Dictionary<string,object>();
dict["Address"] = address;
address["State"] = "WA";
Console.WriteLine(((Dictionary<string,object>)dict["Address"])["State"]);

The deeper is the hierarchy, the uglier is the code. With ExpandoObject it stays elegant and readable.

dynamic expando = new ExpandoObject();
expando.Address = new ExpandoObject();
expando.Address.State = "WA";
Console.WriteLine(expando.Address.State);

Second, as it was already pointed out, ExpandoObject implements INotifyPropertyChanged interface which gives you more control over properties than a dictionary.

Finally, you can add events to ExpandoObject like here:

class Program
{

   static void Main(string[] args)
   {
       dynamic d = new ExpandoObject();

       // Initialize the event to null (meaning no handlers)
       d.MyEvent = null;

       // Add some handlers
       d.MyEvent += new EventHandler(OnMyEvent);
       d.MyEvent += new EventHandler(OnMyEvent2);

       // Fire the event
       EventHandler e = d.MyEvent;

       if (e != null)
       {
           e(d, new EventArgs());
       }

       // We could also fire it with...
       //      d.MyEvent(d, new EventArgs());

       // ...if we knew for sure that the event is non-null.
   }

   static void OnMyEvent(object sender, EventArgs e)
   {
       Console.WriteLine("OnMyEvent fired by: {0}", sender);
   }

   static void OnMyEvent2(object sender, EventArgs e)
   {
       Console.WriteLine("OnMyEvent2 fired by: {0}", sender);
   }
}
Alexandra Rusina
Interesting. Thanks for the info re: events. That was a new one for me.
Reed Copsey
Nice, thanks :)
leppie
@ ReedYes, events are not yet documented for ExpandoObject. This particular example actually came up in the discussion on the blog. I will probably add it to documentation later.
Alexandra Rusina
+2  A: 

Resharper 5.0 supports intellisense on ExpandoObject properties.

Merrick Chaffer