【问题标题】:what is the difference between Anonymous Class Array and Object Array?匿名类数组和对象数组有什么区别?
【发布时间】:2014-05-06 15:04:29
【问题描述】:

我不明白Anonymous Classobject Class 之间的区别

如果我有一个匿名类型对象:

var x = new []
        {
            new {name = "x", phone = 125},
            new {name = "f", phone = 859},
            new {name="s",phone=584}
        };

我可以看到如何遍历它并获取执行此操作的属性的值x.name ...

但是如果我把它改成object

var x = new Object[]
        {
            new {name = "x", phone = 125},
            new {name = "f", phone = 859},
            new {name="s",phone=584}
        };

然后,如果我循环通过它,我将无法访问属性?? 我尝试了不同的方法来从这个对象中获取值,但我失败了,我可能错过了什么吗?生成object array 有什么意义,我该如何使用它?

我知道我不能做这样的事情:new Object[] {name = 'x' ...

【问题讨论】:

  • 我一直以为它只是一个别名,比如string/String,或者object/Object
  • @mason 新建一个字符串,然后按F12,你会看到字符串和对象不是原始类型
  • @mason C# 并没有真正的“原始类型”概念。这是一个俚语,并且没有很好的定义。你应该避免使用它。此外,patxy 完全正确,string 只是String 的别名。它们完全可互换,并且编译器将在其处理的早期将string 的所有实例替换为global::System.String。在任何给定的情况下,没有令人信服的理由使用其中一个。 (除非你做了一些邪恶的事情,比如创建自己的 String 类,其中 string 仍将引用系统类型。)
  • @Servy 我从来没有说过你必须使用一种或另一种方式。我刚才说what the common practice is。这本身就应该是一个令人信服的理由。
  • @mason 这不是一种特别普遍的做法,也没有任何特别令人信服的理由让这种做法存在。我几乎从不使用String,并且在任何地方都使用string,甚至你自己链接到的帖子也表明这正成为MS建议的更普遍的做法。

标签: c#


【解决方案1】:

对象数组可以存储任何值。例如,这不会产生任何错误:

var x = new Object[]
        {
            new {name = "x", phone = 125},
            new {name = "f", phone = 859},
            new {name = "s", phone = 584}
        };
x[0] = "foo";

而匿名类的数组是针对特定匿名类的强类型。所以,这会产生一个错误:

var x = new[]
        {
            new {name = "x", phone = 125},
            new {name = "f", phone = 859},
            new {name = "s", phone = 584}
        };
x[0] = "foo"; // Cannot implicitly convert type 'string' to 'AnonymousType#1'

换句话说,编译器确保匿名类数组的元素是该匿名类的实例(或 null)。

这就是为什么当你编写这样的循环时:

for (var instance in x)
    Console.WriteLine(x.name);

x 被声明为匿名类的数组时它会起作用,因为编译器可以推断该数组的所有元素都是匿名类的实例。但是,当x 被声明为对象数组时,编译器无法推断出该数组元素的实际类型(只是它们继承自 Object,其中包括 .NET 中的所有值)。

【讨论】:

  • 是否有任何方法可以遍历对象并获取属性值,其中一个答案建议dynamic,我知道这不是一个好习惯
  • @MinaGabriel 目前尚不清楚您要完成什么,所以我不能说 最佳 答案是什么,但如果您愿意,您绝对可以使用 dynamic需要。如果您需要更明确地控制它如何迭代属性,您也可以使用反射。但是,仅从您向我们展示的代码来看,根本不清楚是否需要任何这些。您是否有理由要使用对象数组而不是匿名类数组?
  • 不,我只是想知道它们之间的区别
【解决方案2】:

在这两种情况下,数组都是强类型的。在这两种情况下,数组都包含相同匿名类型的对象。唯一的区别是,在第一种情况下,数组具有匿名对象的类型,因此编译器知道其中对象的属性,而在第二种情况下,编译器不知道这些属性。

我尝试了不同的方法来从这个对象中获取值,但我失败了,我可能错过了什么吗?

这些属性仍然存在,您可以通过反射或使用 C# 4 的 dynamic 类型来访问它们:

var x = new Object[]
    {
        new {name = "x", phone = 125},
        new {name = "f", phone = 859},
        new {name="s",phone=584}
    };
var bigPhone = x.Cast<dynamic>().Where(v => v.phone > 500);
foreach (dynamic item in bigPhone) {
    Console.WriteLine("name={0}, phone={1}", item.name, item.phone);
}

请注意,此解决方案不是使用第一个示例中的静态类型数组的等效替代方案。这只是一种解决静态类型丢失情况的方法。

【讨论】:

  • 这里正确的解决方案是推断匿名类型的类型,就像在OP的第一个示例中所做的那样,而不是使用dynamic,这会导致各种问题。
  • @Servy 这里没有“正确”或“不正确”的解决方案 - 事实上,OP 并没有问什么是正确的,什么不是,他在问有什么区别。我不建议他使用dynamic“解决方案”,只是展示一种方法来取消键入对象。
【解决方案3】:

当你将变量声明为时

var x = new Object[]
    {
        new {name = "x", phone = 125},
        new {name = "f", phone = 859},
        new {name="s", phone=584}
    };

x[whatever]Object 类型,所以只能作为一个使用。 Object 没有 namephone 这样的字段,所以你自然无法访问它们。

【讨论】:

  • so you can only use it as one是什么意思
  • 您只能访问字段并调用Object 类中可用的方法。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2011-01-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-12-30
  • 2015-10-24
  • 2011-01-21
相关资源
最近更新 更多