【问题标题】:Initializing a dictionary with anonymous objects使用匿名对象初始化字典
【发布时间】:2014-10-17 11:19:18
【问题描述】:

我正在尝试执行以下操作。

private static Dictionary<int, object> MAPS = new Dictionary<int, object>
{
  {1, new {1, 2, 3}}
};

根据MSDN,它不像我预期的那样工作,所以我很确定问题在于我使用的是匿名对象。假设我不想为我的东西创建一个新类型并且仍然想将所有映射保留在同一个字典中,我该怎么办?

我见过this answer,但它现在有点过时了,所以我希望框架中有一些新的东西。

【问题讨论】:

  • 而不是说 "doesn't work as Id expect" 如果您显示实际的编译器错误会很有帮助,即 "Invalid匿名类型成员声明器。必须使用成员分配、简单名称或成员访问来声明匿名类型成员".
  • @CodeCaster 点已被占用。我认为这是基本的东西,我只是脑子有问题。但你是对的,没有争论。 :)

标签: c# dictionary initialization anonymous-types


【解决方案1】:

如果你想要一个ints 的数组作为值,试试这个。

private static Dictionary<int, object> MAPS = new Dictionary<int, object>
{
  {1, new[] {1, 2, 3}}
};

如果你想要一个匿名类,或者这个

private static Dictionary<int, object> MAPS = new Dictionary<int, object>
{
  {1, new { a = 1, b = 2, c = 3}}
};

或者最好不要使用object。使用int[]List&lt;int&gt; 作为int 的集合,或者如果需要特定值,可以声明一个类或结构。如果每个值只需要 3 个 ints,甚至可以使用 Tuple&lt;int,int,int&gt;。但是,一般来说,您应该尽量避免在object 之间进行转换。

【讨论】:

  • 哦,我尝试在 both 新运算符 角度中的对象类型上设置括号。我试过冒号而不是等号。愚蠢的 JSON 伤害了我... :) +1
  • 是否可以输入abc 没有为它们声明一个类?
  • 它们将隐式采用您设置的类型,因此如果需要,您可以转换该值。但是这里使用匿名类的主要问题是,当您从字典中提取值时,您无法对其进行强制转换。您可能想考虑使用dynamic 而不是object
【解决方案2】:

匿名类型只是具有属性的类型,您的匿名类型没有属性:

private static Dictionary<int, object> MAPS = new Dictionary<int, object>
{
    {1, new { Prop1 = 1, Prop2 = 2, Prop3 = 3}}
};

但是你想如何从对象转换到那个匿名类型呢?

编辑这里的问题很好。我必须强制转换 MAPS[1][0] 还是有办法在其中隐式强制类型?

如果没有像这种扩展方法这样的 hack,你不能将对象转换为匿名类型:

public static T CastByPrototype<T>(this object obj, T prototype)
{
    return (T)obj;
}

它使用原型匿名类型,例如:

var prototype = new { Prop1 = 0, Prop2 = 0, Prop3 = 0 };

现在可以了:

var value = MAPS[1].CastByPrototype(prototype);  // you can use value.Prop1

如果原型具有不同的属性(以相同的顺序),它会失败并返回 InvalidCastException

【讨论】:

  • 好问题,不过。我必须强制转换 MAPS[1][0] 还是有办法在其中隐式强制类型?
  • @KonradViltersten 如果您希望能够使用MAPS[1][0] 获得一个值,那么为什么不改为Dictionary&lt;int, int[]&gt;Dictionary&lt;int, List&lt;int&gt;&gt; 呢?
【解决方案3】:

除了@TimSchmelter 和@juharr 的答案之外,如果您希望能够通过它们的名称引用属性,但又不想创建一个可以使用dynamic 的类(尽管显然您不会获得任何智能感知,因此它的使用受到限制):

Dictionary<int, object> MAPS = new Dictionary<int, object>
{
    {1, new { a = 1, b = 2, c = 3} as dynamic}
};

Console.WriteLine(((dynamic)MAPS[1]).b); //prints 2

或者,如果您将 Dictionary 设为 Dictionary&lt;int, dynamic&gt;,您可以放弃演员阵容,这会让生活变得更轻松:

Dictionary<int, dynamic> MAPS = new Dictionary<int, object>
{
    {1, new { a = 1, b = 2, c = 3}}
};

Console.WriteLine(MAPS[1].b); //prints 2

使用objectdynamic 的唯一好处是您可以在其中存储不同类型的集合。如果您只存储ints,那么您最好使用List&lt;int&gt;int[]

【讨论】:

    【解决方案4】:

    new {1, 2, 3} 的语法是not a collection initializer nor an anonymous object initializer。您要创建什么类型的对象?

    使用new { elements = new[] { 1, 2, 3 } } 之类的东西为匿名对象提供一个包含整数的elements 属性。

    或者您可以命名各个属性:new { foo = 1, bar = 2, baz = 3 }

    【讨论】:

    • 我想要一本字典,对于给定的整数,我会给出两个不同的整数。
    猜你喜欢
    • 1970-01-01
    • 2016-12-02
    • 2013-06-07
    • 2016-09-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-06-27
    • 1970-01-01
    相关资源
    最近更新 更多