为什么匿名类型的属性不能在数组中交换?

4
我知道在C#中可以像这样声明一个匿名类型的数组:

这个文本内容需要翻译。

var anons = new[]
{
    new { name = "" , something = ""},
    new { name = "", something = "" }
};

我理解所有的对象需要具有相同的属性,否则就无法迭代并使用这些属性,例如:

foreach (var anon in anons)
{
    Console.WriteLine(anon.name);
}

但是我不理解他们的属性为什么需要按照相同的顺序? 例如,以下代码将无法编译:
var anons = new[]
{
    new { name = "" , something = ""},
    new { something = "", name = "" }
};

为什么这不被允许,因为在一个普通的对象中,属性可以按照任意顺序声明,并且代码的其余部分可以使用它们,就像现在一样?


1
这可能是为了简化编译器和哈希码生成,并防止ToString()输出的差异,但我不确定我们中的任何人都能解释为什么做出了特定的设计决策。 - user47589
@Amy,这实际上更多是关于编译器设计的问题,而不是如何做某事的问题,在这种情况下确实有一些人可以完全回答它。我只是希望得到最接近现实的答案。 - meJustAndrew
2个回答

7
根据匿名类型的文档:https://learn.microsoft.com/en-us/dotnet/csharp/programming-guide/classes-and-structs/anonymous-types,如果同一程序集中的两个或多个匿名对象初始化器指定了一个“按相同顺序具有相同名称和类型属性的序列”,编译器将把这些对象视为同一类型的实例。它们共享相同的编译器生成的类型信息。换句话说,您正在创建两个匿名类型,并且属性名称和属性类型的序列不匹配。虽然它们在视觉上看起来很相似,但编译器将它们视为两种不同的类型,这意味着它无法推断数组声明的一个类型。

没错。我还建议在答案中添加此链接,以帮助澄清两种匿名类型之间编译差异的区别。 - Aly Elhaddad
在这种情况下,我不确定它是否有帮助。我们已经知道编译器正在生成两种类型,每个属性序列一个。看到编译器生成的代码很有趣,但它只是确认了我们所知道的内容。 - Scott Hannen
我可以看到编译器不允许将交换属性的两个不同匿名对象声明为数组,但是为什么呢?我的意思是,这是因为实现成本太高而不值得吗,还是有其他原因? - meJustAndrew
1
这不是一个答案,而是一个需要考虑的情景:如果不是两个属性,而是更多的属性 - 比如说二十个 - 并且两个声明它们的顺序完全不同。从技术上讲,编译器可以解决这个问题,并确定它们是相同的类型,但看起来会非常混乱。如果你认为它们是相同的,但编译器说它们不是,你该怎么办?你必须对所有属性进行排序,以找出差异所在。 - Scott Hannen
实际上,我认为他们没有理由允许在不同的顺序下拥有属性,这就是为什么编译器现在会报错的原因。@ScottHannen,请使用@符号标记人,这样当您回复他们时,他们会收到通知 :) - meJustAndrew

-1

虽然Scott提供的答案基本上是正确的,但并没有完全回答“为什么”问题。由于这更多关于匿名类型数组的编译器设计的问题,而我们大多数人都无法给出清晰的答案,我将保持问题开放,并暂时不接受答案,直到有人回答“为什么”的问题。同时,我在此留下以下理论:

关于这个问题

为什么它们的属性需要具有相同的顺序?

为什么不呢?

因为现在可以声明一个匿名类型数组,对象内部的属性顺序交换对任何人都没有帮助。

相反,更改匿名类型对象中对象内部属性的顺序会导致误导,并且出于一致性的考虑应该避免这样做。在这种情况下,针对试图交换对象属性的程序员应显示警告或至少显示消息,因此从一开始就将其设置为错误并消除C#编译器自动排序属性的需求。

总之:将属性始终保持相同的顺序不是缺失功能,而是一项特征。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接