【问题标题】:How does ToString on an anonymous type work?匿名类型的 ToString 如何工作?
【发布时间】:2013-05-23 13:20:10
【问题描述】:

我在搞乱匿名类型,我不小心将它输出到控制台上。它看起来基本上是我如何定义的。

这是一个重现它的简短程序:

using System;
class Program
{
    public static void Main(string[] args)
    {
        int Integer = 2;
        DateTime DateTime = DateTime.Now;
        Console.WriteLine(new { Test = 0, Integer, s = DateTime });
        Console.ReadKey(true);
    }
}

现在,输出是:

{ Test = 0, Integer = 2, s = 28/05/2013 15:07:19 }

我尝试使用 dotPeek 进入程序集以找出原因,但没有任何帮助。[1]这是 dotPeek 的代码:

// Type: Program
// Assembly: MyProjectName, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null
// Assembly location: Not telling you! :P
using System;
internal class Program
{
  public static void Main(string[] args)
  {
    Console.WriteLine((object) new
    {
      Test = 0,
      Integer = 2,
      s = DateTime.Now
    });
    Console.ReadKey(true);
  }
}

根本没有太大的不同。

那么它是如何工作的呢?它是如何输出的呢?

注意事项:

[1]:我忘记打开“显示编译器生成的代码”,这就是我不知道它是如何工作的原因。

【问题讨论】:

  • 设计?这里的实际问题/问题是什么?
  • 我想知道它是如何工作的!
  • 也许 ToString 使用反射.. 来打印每个键值对。
  • @LewsTherin 我认为这太过分了,但这是可能的!
  • @Jeppe 这将是一个挑战:规范没有为 ToString 在匿名类型上定义任何行为

标签: c# .net tostring anonymous-types


【解决方案1】:

只是为了向 HuorSwords 答案添加一些代码,编译器将为您的示例生成 ToString 方法,如下所示:

public override string ToString()
{
    StringBuilder stringBuilder = new StringBuilder();
    stringBuilder.Append("{ Test = ");
    stringBuilder.Append((object) this.<Test>__Field);
    stringBuilder.Append(", Integer = ");
    stringBuilder.Append((object) this.<Integer>__Field);
    stringBuilder.Append(", s = ");
    stringBuilder.Append((object) this.<s>__Field);
    stringBuilder.Append(" }");
    return ((object) stringBuilder).ToString();
}

当您在编译时拥有所有必需的元数据时,在此处使用反射会降低性能。

使用 dotPeek 进行反编译,此版本可能因使用的反编译器而异。

注意:由于您还使用 dotPeek 进行了反编译,因此请尝试查看 Root Namespace。在那里你会发现类似的东西:

[DebuggerDisplay("\\{ Test = {Test}, Integer = {Integer}, s = {s} }", Type = "<Anonymous Type>")]
internal sealed class <>__AnonymousType0<<Test>

这是定义匿名对象时编译生成的示例。

【讨论】:

  • 我错过的原因是因为我忘记打开“显示编译器生成的代码”。不过谢谢,+1!
【解决方案2】:

使用匿名对象...

编译器生成一个内部密封类,用于建模 匿名类型。匿名类型是不可变的;所有属性 是只读的。该类包含 Equals() 和 GetHashCode() 实现值语义。除此之外 编译器生成显示值的 ToString() 覆盖 每个公共属性。

来源:link

请检查 @Ilya Ivanov 的答案以查看有关此主题的一些代码。

【讨论】:

    【解决方案3】:

    匿名类型仍然是完全定义的类型...简单地说:编译器完全自己生成它们,而您永远看不到名称/实现(只是:它与您在代码中使用的初始化程序匹配)。

    实际上,ToString 在具体操作中未提及关于匿名类型(第 7.6.10.6 节);只有必需 EqualsGetHashCode 在属性方面起作用。规范中的示例(“声明表单的匿名类型”)包含ToString 覆盖。

    MS 编译器添加了基于属性的ToString 实现作为礼貌 - 但也可能是因为默认 ToString 是类型名称,这将本身是没有意义的(毕竟它是匿名的——类型名称很难读,并且包含泛型语法)。坦率地说,仅将其用于调试目的是个好主意。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-09-15
      • 1970-01-01
      • 1970-01-01
      • 2018-01-14
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多