ToString如何在匿名类型上工作?

It'*_*ie. 21 .net c# anonymous-types tostring

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

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

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);
    }
}
Run Code Online (Sandbox Code Playgroud)

现在,输出是:

{ Test = 0, Integer = 2, s = 28/05/2013 15:07:19 }
Run Code Online (Sandbox Code Playgroud)

我尝试使用dotPeek进入程序集找出原因,但没有帮助.[1]这是dotPeek'd代码:

// 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);
  }
}
Run Code Online (Sandbox Code Playgroud)

所以没有太大的不同.

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

笔记:

[1]:我忘了打开"显示编译器生成的代码",这就是我没有得到它如何工作的原因.

Huo*_*rds 15

使用匿名对象......

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

来源:链接

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


Ily*_*nov 15

只是为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();
}
Run Code Online (Sandbox Code Playgroud)

当您在编译时拥有所有必需的元数据时,在此处使用反射将是性能效率低下的.

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

注意:由于您还使用dotPeek进行反编译,请尝试查看根命名空间.在那里你会发现类似的东西:

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

当您定义匿名对象时,这是编译生成的示例.


Mar*_*ell 9

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

其实,ToString没有提及在specificaction(第7.6.10.6)关于匿名类型; 它只是需要的是EqualsGetHashCode工作在性能方面.在本说明书中的实施例("声明匿名类型形式的")都没有包括一个ToString覆盖.

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