匿名类型上的ToString如何工作

本文关键字:何工作 工作 ToString 类型 | 更新日期: 2023-09-27 18:15:37

我使用了匿名类型,不小心将它输出到控制台上。基本上就是我定义的。

下面是一个复制它的短程序:

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如何工作

使用匿名对象…

编译器生成一个内部密封类,该类对匿名类型。匿名类型是不可变的;所有属性是只读的。该类包含Equals()和GetHashCode()实现值语义。此外,编译器生成ToString()的重写以显示该值

来源:link

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

只是为了给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进行反编译,请尝试查看根命名空间。在那里你会发现类似的内容:

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

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

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

实际上,ToString在规范(第7.6.10.6节)中没有提到的;EqualsGetHashCode的性质只要求。规范中的示例(声明了表单的匿名类型)是否包含ToString覆盖?

MS编译器添加了一个基于属性的ToString 实现作为礼貌 -但也可能是因为默认 ToString是类型名,它本身是没有意义的(毕竟,它是匿名的-类型名读起来非常可怕,并且包含泛型语法)。坦率地说,只在调试时使用它是个好主意。