6

我有一个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 并访问这些属性?

4

5 回答 5

13

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

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

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

) 您无法获取类型的名称,您需要该名称才能执行从Object回您创建的类型的转换。您将不得不求助于具有固有缺陷的示例解决方案。

Cast-by-example 是有缺陷的,因为从设计的角度来看,您想要在声明它的函数之外(并且仍然在同一个模块内)访问类型的每个地方,都必须重新有效地声明类型。

这是导致设计和实施草率的重复工作。

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

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

于 2010-02-19T21:25:25.193 回答
8

有几种方法。

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

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

另一种欺骗 .NET 为您提供正确类型的方法称为“通过示例强制转换”,它是这样的:您需要通过泛型方法调用传递您的对象,该方法会将对象作为正确的类型返回,通过推断要返回的正确类型。

例如,试试这个:

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

并使用它:

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

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

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

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

于 2010-02-19T21:23:11.817 回答
3

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

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

于 2010-02-19T21:19:25.490 回答
1

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

于 2010-02-19T21:18:03.897 回答
1

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

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

在这两种情况下,您都不需要拆箱;那是针对值类型的。匿名类型始终是引用类型。

于 2010-02-19T21:18:37.293 回答