匿名类型

时间:2010-02-19 21:15:09

标签: c# anonymous-types unboxing

我有Dictionary(TKey, TValue)喜欢

Dictionary<int, ArrayList> Deduction_Employees = 
    new Dictionary<int, ArrayList>();

后来我向该数组列表添加了一个像这样的匿名类型

var day_and_type = new {
    TheDay = myDay,
    EntranceOrExit = isEntranceDelay
};

Deduction_Employees[Employee_ID].Add(day_and_type);

现在我怎样才能取消该var并访问这些属性?

5 个答案:

答案 0 :(得分:13)

首先,您不是拆箱类型。匿名类型是引用类型,而不是结构。

即使你可以在声明它们的方法之外技术上创建相同类型的实例(根据C#3.0语言规范的7.5.10.6节,其中声明:

  

在同一个程序中,两个匿名   指定a的对象初始值设定项   它的属性序列   中的名称和编译时类型   相同的顺序将产生实例   相同的匿名类型。

)您无法获取该类型的名称,以便从Object执行强制转换回您创建的类型。你不得不诉诸cast-by-example solution,这本身就是有缺陷的。

逐个示例是有缺陷的,因为从设计的角度来看,每个想要访问它所声明的函数之外的类型的地方(并且仍在同一个模块中),你必须有效地再次声明类型

这是一种重复的努力,导致设计和实施的草率。

如果您使用的是.NET 4.0,那么可以将对象实例放在动态变量中。但是,主要缺点是缺乏成员访问的编译时验证。您可能很容易拼错该成员的名称,然后您遇到运行时错误而不是编译时错误。

最终,如果您发现需要在声明的方法之外使用匿名类型,那么唯一的好方法是创建具体类型并将匿名类型替换为具体类型

答案 1 :(得分:8)

有几种方法。

由于评论似乎表明我建议你这样做,让我说清楚:你应该为你的对象创建一个命名类型,因为你打算传递它。

首先,您可以使用Reflection,这里已经指出了另一个答案。

另一种方法,它使.NET成为正确的类型被称为“按示例执行”,它是这样的:你需要通过泛型方法调用传递你的对象,它会将对象返回为正确的类型,通过推断正确的类型返回。

例如,试试这个:

private static T CastByExample<T>(T example, object value)
{
    return (T)value;
}

并使用它:

var x = CastByExample(new { TheDay = ??, EntranceOrExit = ?? }, obj);

两个??斑点,您只需要传递适合这些属性的数据类型的东西,不会使用这些值。

这利用了这样一个事实:在同一个程序集中,包含完全相同属性,相同类型,相同顺序的多个匿名类型将映射到同一个单一类型。

但是,此时您应该创建一个命名类型。

答案 2 :(得分:3)

  

匿名类型具有方法范围。要在方法边界外传递匿名类型或包含匿名类型的集合,必须先将类型转换为对象。然而,这打败了匿名类型的强类型。如果必须存储查询结果或将它们传递到方法边界之外,请考虑使用普通的命名结构或类而不是匿名类型。

来源:http://msdn.microsoft.com/en-us/library/bb397696.aspx

答案 3 :(得分:1)

不,你不能。您只能使用反射访问属性。编译器无法知道类型是什么,并且由于它是匿名类型,因此您也无法将其强制转换。

答案 4 :(得分:1)

如果您使用的是.NET 1.x - 3.x,则必须使用反射。

如果使用.NET 4.0,则可以使用动态类型并调用预期的属性。

在这两种情况下你都不需要拆箱;这是价值类型。匿名类型始终是引用类型。