与对象的词典作为价值

我在这里疯了。 这可能是因为我错过了一些规则,但如果是这样,请告诉我。

我正在尝试创建一个带有键的字符串和一个匿名对象作为值的Dictionary 。 或者,实际上我不只是尝试,我正在做。 但是当我想改变对象中的特定参数时,它就出错了。

我像这样声明字典:

 var areas = new Dictionary { {"Key1", new {name = "Name1", today = 0, all = 0}}, {"Key2", new {name = "Name2", today = 0, all = 0}}, ... } 

然后我假设我可以这样做:

 foreach (var area in areas.Keys.ToArray()) { var areaname = areas[area].name; } 

但Visual Studio不同意,并拒绝编译。 但是,如果我写这篇文章,一切都按照我的想法运作 – 但这并没有真正帮助我,这只会让我更加沮丧。

 var areaname = new { name = "Nametest", today = 0, all = 0 }; var testname = areaname.name; 

我究竟做错了什么? 为什么它不适合我? 这样做根本不可能吗?

谢谢你的所有答案,他们肯定清理了一下! 我想我可能一直在混淆类型对象对象的想法,即C#中的类,而不是沮丧。 我将重新思考整个设计业务,并可能做一些完全不同的事情,而不是使用邪恶或肮脏的解决方案。 虽然有趣,但我认为我与C#的关系还没有发展到那么远!

这不起作用,因为您已将字典声明为Dictionary

你可以尝试使用Dictionary

这不会编译,因为字典中的值是object类型,而object不包含属性name

如果您使用的是.NET 4,则可以将类型从object更改为dynamic

话虽如此,我强烈反对这一设计决定。 你真的应该为此创建一个类。

这不起作用,因为您已将字典声明为Dictionary

C#在后台为您创建一个具有这些属性的新类型(您无法访问)(此处称为匿名类型)。 您可以直接使用它的唯一时间是它仍然是var类型 – 只要将它添加到该字典,它就会被转换为object ,因此您无法再访问这些属性。

选项1

你可以尝试使用Dictionary 。 Dynamic将能够访问这些属性 – 但这仅在C#/ .Net 4.0中受支持

选项2

您可以使用称为演示的技术(通过示例演员)获取类型。 这不是一个记录在案的function,是浪费,有点像黑客。 这是一个可怕的邪恶伎俩 – 特别是因为它无法跨组件工作。

 public static T Demonstrate(this T demonstration, object value) { return (T)value; } 

然后,您可以访问原始属性,如下所示:

 var area = new { name = "", today = 0, all = 0 }.Demonstrate(areas[name]); var areaName = value.name; 

选项3 这是老实说最好的方法

写一堂课。 如果您喜欢C#编译器执行所有EqualsGetHashCodeToString的事实,您可以使用ILSpy之类的东西来获取原始代码。 从而:

 class AreaInfo { public string Name { get; set; } public int Total { get; set; } public int All { get; set; } public override bool Equals(object obj) { var ai = obj as AreaInfo; if (object.ReferenceEquals(ai, null)) return false; return Name == ai.Name && Total == ai.Total && All == ai.All; } public override int GetHashCode() { var hc = 0; if (Name != null) hc = Name.GetHashCode(); hc = unchecked((hc * 7) ^ Total); hc = unchecked((hc * 21) ^ All); return hc; } public override string ToString() { return string.Format("{{ Name = {0}, Total = {1}, All = {2} }}", Name, Total, All); } } 

纠正你的字典:

 var areas = new Dictionary { {"Key1", new AreaInfo() {Name = "Name1", Today = 0, All = 0}}, {"Key2", new AreaInfo() {Name = "Name2", Today = 0, All = 0}}, ... }; 

现在事情会像你期望的那样发挥作用。

要使Dictionary的值具有正确的匿名类型,请执行以下操作:

 var areas=new[] { new {Key="Key1", Value=new {name="Name1", today=0, all=0}}, new {Key="Key2", Value=new {name="Name2", today=0, all=0}}, }.ToDictionary(kv => kv.Key, kv => kv.Value); 

然后您的代码将按预期工作:

 foreach(var area in areas.Keys.ToArray()) { var areaname=areas[area].name; } 

匿名类型的细节在创建它们的程序集之外是不可移植的,并且除了它们创建的方法之外不容易看到。你应该使用onousous类型,或者如果你想采用动态方法则动态。

†这里有一个邪恶的伎俩,我故意不提,因为它是邪恶的。