【问题标题】:Why does C# not allow anonymous cast to objects?为什么 C# 不允许匿名强制转换为对象?
【发布时间】:2017-12-16 00:29:34
【问题描述】:

我想知道不允许这种类型转换的原因。这个主题已经在这个post in SO 中讨论过了,但我想了解一下为什么这在本地是不可能的。

为什么这些转换失败了?

OBS:我知道可以通过反思来做到这一点。

IList<People> peopleList = new List<People>()
{
    new People() { Name = "Again", Age = 10 },
    new People() { Name = "Over", Age = 20 },
    new People() { Name = "Jonh", Age = 30 },
    new People() { Name = "Enzo", Age = 40 },
};

var anonymous = (from p in peopleList
                select new
                {
                    Name = p.Name,
                    Age = p.Age
                });

// Does not work
IList<People> listt = (IList<People>)anonymous; 
//Does not Work
IList<People> listt = (anonymous as List<People>);

【问题讨论】:

  • 我想你认为它应该工作会很有趣。匿名类型不是另一种类型,即使它具有相同的字段。对于任何其他类型,无论是否匿名,都是如此。这就是语言的构建方式,C# 中没有鸭子类型。
  • 为什么它应该起作用?它是匿名类型,而不是 People 实例。没有可以想象的从一个到另一个的演员阵容。 Cast 的意思是“将此对象视为其他等效类型”。没有什么说这个匿名类型等同于People。如果你用它来代表宠物呢?
  • 您的匿名类型不是People,并且这两种类型之间没有转换。为什么该演员阵容有效?编译器应该如何知道如何将People 转换为您的匿名类型?即使是这样,IList&lt;sometype&gt; 仍然是与 IList&lt;People&gt; 完全不同的类型。
  • 它不起作用的“低级”原因是因为它没有被定义为 C# 语言规范中支持的强制转换。
  • 这被称为“Duck Typing”顺便说一句。如果它像鸭子一样走路,像鸭子一样嘎嘎叫,那就像鸭子一样对待它。除了一些非常特殊的情况外,它在 C# 中作为一流的语言功能不可用。

标签: c# linq casting anonymous-types


【解决方案1】:

问题是为什么anonymous 不能成功转换为IList&lt;People&gt; 或List&lt;People&gt;。

  • 查询表达式的值是可以执行查询的对象。它不是查询执行的结果集。 anonymous 实现了IEnumerable&lt;T&gt;,而不是IList&lt;T&gt;,当然它也不是List&lt;T&gt; 的子类型。所以它不能转换为任何IList&lt;T&gt; 或List&lt;T&gt; 类型。如果这是您想要的,请使用 ToList() 执行查询并将结果集存储在列表中。
  • 可以将查询转换为IEnumerable&lt;People&gt; 吗?不,它是一系列匿名类型的对象,它们复制了与People 关联的一些值。所以它是一个匿名对象的序列,而不是一个人的序列。

我还注意到,在新的 C# 7 代码中,如果可以的话,最好在应用程序中使用元组而不是匿名类型。它们在类型系统中的支持更好,产生的收集压力也更小。

【讨论】:

    猜你喜欢
    • 2019-03-12
    • 2019-12-21
    • 2014-12-07
    • 2020-07-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多