为什么不能将字段和 属性 声明为匿名类型?

Why you cannot declare a field and property as having an anonymous type?

我 运行 在做我的工作时遇到了一个问题,即将软件从闪存 AS3 移植到 .NET/Mono。在 AS3 代码库中,我可以找到许多 Object 像这样初始化的声明:

private const MAPPING:Object =
{
    ssdungf:'flydung',
    ssdungt:'flydung',
    superfutter:'superfeed'
}

对我来说最好的选择是在 C# 中使用这样的匿名类型:

var MAPPING = new
{
    ssdungf = "flydung",
    ssdungt = "flydung",
    superfutter = "superfeed"
};

问题是...让我引用 MSDN (source):

You cannot declare a field, a property, an event, or the return type of a method as having an anonymous type

但他们没有说为什么。

所以问题仍然存在:为什么不能声明字段并且 属性 具有匿名类型?为什么 .NET 创建者将其从该选项中删除?

我收到来自 SO 的警告,我的问题似乎是主观的,但我认为它根本不是 - 需要有 objective 原因。

至于我,我没有看到任何障碍,但不知何故它不受支持。由于编译器可以很容易地为字段或 属性 生成 class 的类型,其方式与对局部变量的处理方式相同。

我的选择是使用 dynamic 类型,但不幸的是,我使用的 Mono 引擎被从中剥离了。

另外,我的选择是使用对象类型并使用稍后的反射来查找这些字段:

 private static readonly object MAPPING = new
 {
     ssdungf = "flydung",
     ssdungt = "flydung",
     superfutter = "superfeed"
 };

但是我会说使用反射这种情况很脏。

我试图找到答案,但我真的没有找到任何答案。以下是类似问题的一些 SO 答案,但没有回答原因:

Can a class property/field be of anonymous type in C# 4.0?

Declaring a LIST variable of an anonymous type in C#

How do you declare a Func with an anonymous return type?

一个异常的问题属性是:你get/set怎么样?

假设它会起作用:

class MyClass
{
    public MyField = new { TheValue = "Hello World" };
}

现在在您的消费代码中,您将编写代码来读取代码:

MyClass m = new MyClass();
m.MyField.TheValue = "newValue";

这与 MyField 的类型有何不同?您得到的只是您可以省略两三行代码而一无所获。但我认为您可能会产生很多问题,因为没有人知道他可以从该成员分配 to/expect 什么。

此外,您不能对匿名对象做太多事情,基本上您可以设置并读取它。没有可以调用的方法(EqualsGetHashCode 继承自 object),因此机会非常少。

最后但同样重要的是,匿名对象通常用作临时对象,例如在 Select 语句中。当你使用它时,你说:这种类型将仅在当前特定范围内使用,并且可以作为内部实现细节被整个世界忽略。创建匿名类型的 属性 会将这样的细节暴露给外部。当然,您可能会争辩说设计者至少可以允许 private 成员使用它们,但我想这样做会白白绕过可访问性的完整概念。

Why you cannot declare a field and property as having an anonymous type?

因为 C# 是静态类型的,所以任何内存位置都必须指定类型,声明也是如此。对于局部变量,我们可以从上下文中推断出它是否与 var 声明同时初始化,但对于即使类型没有名称也可用的类型来说,这是一个 shorthand。

具有匿名类型(即静态绑定但难以描述的类型)的字段是什么意思?

dynamic 确实是与您正在移植的代码最接近的类比,但由于您无法使用它,您可能会考虑使用 IDictionary<string, object>(顺便说一下 ExpandoObject,通常与 dynamic 一起使用,使对象的行为更像 javascrpt 对象,在幕后工作)。与为所需对象创建 class 相比,这会更慢且类型安全性更低,但可以工作。