被添加到. net 4中的ExpandoObject类允许您在运行时任意地为对象设置属性。

与使用Dictionary<string, object>,甚至哈希表相比,这有什么优点吗?据我所知,这只是一个哈希表,您可以使用稍微简洁的语法访问它。

举个例子,为什么是这样:

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

比:更好的或有本质区别的:

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

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

使用ExpandoObject而不是使用任意的字典类型有什么真正的好处,除了不明显地表明您使用的是将在运行时确定的类型。


当前回答

在valueTuples之后,ExpandoObject类有什么用? 这6行代码与ExpandoObject:

dynamic T = new ExpandoObject();
T.x = 1;
T.y = 2;
T.z = new ExpandoObject();
T.z.a = 3;
T.b= 4;

可以用元组写在一行中:

var T = (x: 1, y: 2, z: (a: 3, b: 4));

此外,有了元组语法,你就有了强大的类型推断和inlisense支持

其他回答

在某些情况下,这很方便。例如,我将把它用于模块化shell。每个模块都定义了自己的配置对话框,该对话框与它的设置绑定。我为它提供了一个ExpandoObject,因为它是Datacontext,并将值保存在我的配置存储。这样,配置对话框编写者只需要绑定到一个值,它就会自动创建和保存。(当然,提供给模块用于使用这些设置)

它只是比字典更容易使用。但每个人都应该意识到,在内部它只是一本词典。

就像LINQ只是语法糖一样,但有时它让事情变得更简单。

所以直接回答你的问题:它更容易写,也更容易读。但从技术上讲,它本质上是Dictionary<string,对象>(您甚至可以将其转换为一个以列出值)。

var obj = new Dictionary<string, object>;
...
Console.WriteLine(obj["MyString"]);

我认为这只会起作用,因为所有东西都有一个ToString(),否则你必须知道它的类型,并将“对象”转换为该类型。


有些方法比其他方法更有用,我尽量讲得透彻些。

It may be far more natural to access a collection, in this case what is effectively a "dictionary", using the more direct dot notation. It seems as if this could be used as a really nice Tuple. You can still call your members "Item1", "Item2" etc... but now you don't have to, it's also mutable, unlike a Tuple. This does have the huge drawback of lack of intellisense support. You may be uncomfortable with "member names as strings", as is the feel with the dictionary, you may feel it is too like "executing strings", and it may lead to naming conventions getting coded in, and dealing with working with morphemes and syllables when code is trying understand how to use members :-P Can you assign a value to an ExpandoObject itself or just it's members? Compare and contrast with dynamic/dynamic[], use whichever best suits your needs. I don't think dynamic/dynamic[] works in a foreach loop, you have to use var, but possibly you can use ExpandoObject. You cannot use dynamic as a data member in a class, perhaps because it's at least sort of like a keyword, hopefully you can with ExpandoObject. I expect it "is" an ExpandoObject, might be useful to label very generic things apart, with code that differentiates based on types where there is lots of dynamic stuff being used.


如果你能一次钻到多个层次就好了。

var e = new ExpandoObject();
e.position.x = 5;
etc...

这不是最好的例子,想象一下在你自己的项目中优雅的使用。

遗憾的是,你不能让代码构建其中的一些,并将结果推送到智能感知。但我不确定这是怎么回事。

如果它们能像成员一样有价值就好了。

var fifteen = new ExpandoObject();
fifteen = 15;
fifteen.tens = 1;
fifteen.units = 5;
fifteen.ToString() = "fifteen";
etc...

既然你提到的那篇MSDN文章是我写的,我想我必须回答这个问题。

首先,我预料到了这个问题,这就是为什么我写了一篇博客文章,展示了c# 4.0中ExpandoObject: Dynamic的一个或多或少的真实用例:介绍ExpandoObject。

简单地说,ExpandoObject可以帮助您创建复杂的分层对象。例如,假设你在一个字典中有一个字典:

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"]);

层次结构越深,代码就越丑。使用ExpandoObject,它保持优雅和可读。

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

第二,正如已经指出的,ExpandoObject实现了INotifyPropertyChanged接口,它比字典更能控制属性。

最后,你可以像这样向ExpandoObject添加事件:

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;

       e?.Invoke(d, new EventArgs());
   }

   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);
   }
}

另外,请记住,没有什么可以阻止您以动态方式接受事件参数。换句话说,您可以使用EventHandler<dynamic>而不是使用EventHandler,这将导致处理程序的第二个参数是动态的。

在valueTuples之后,ExpandoObject类有什么用? 这6行代码与ExpandoObject:

dynamic T = new ExpandoObject();
T.x = 1;
T.y = 2;
T.z = new ExpandoObject();
T.z.a = 3;
T.b= 4;

可以用元组写在一行中:

var T = (x: 1, y: 2, z: (a: 3, b: 4));

此外,有了元组语法,你就有了强大的类型推断和inlisense支持

我认为这将在语法上有好处,因为您将不再使用字典来“伪造”动态添加的属性。

我认为,还有与动态语言的互操作。