返回首页

{A}{S0}简介
良好的老问题:如何找到一个代码执行过程中的变量的值?断点和观察窗口调试器是伟大的,但如果程序可以在适当的时候在合适的地方停下。不幸的是,条件并不总是那么理想和倾销所需的值到一个日志文件或控制台,为未来的分析,是一个比较现实的选择。
另一种常见情况是一个简单的调试运行和忘记的实用工具,需要生产以最少的编码人类可读的输出。没有这样的工具是用于非技术用户和美化的输出是不是一个优先事项,尚未产生有用的输出所花费的时间是。
在这两种情况下,我经常发现自己写代码如下:

class C { 

    public int X; 

    public string Y; 

    public DirectoryInfo Child; 

    public int Z; 

}

...

C c=...



// Oops, that prints just "MyNamespace.C", hardly useful

// Debug.WriteLine("c="+c);



Debug.WriteLine("--- Value of c ----");

Debug.WriteLine("c.X="+c.X);

Debug.WriteLine("c.Y="+c.X); // Oops, dumping the wrong field

Debug.WriteLine("c.Child=FileInfo 

    { Name="+c.Child.Name +"}"); // This will sometimes throw NullReference exception

Debug.WriteLine("-------"); // Forgot to dump Z field :(

不仅如此冗长,恼人的写,这样的代码的第一次迭代往往是无用的。要么被倾倒的对象没有覆盖其ToString方法,或输出混乱是因为错别字,或不包含有用的领域,或抛出异常,或一次多个线程执行的代码和Debug.WriteLine输出是混合在一起。事情变得更糟时有匿名对象,数组,枚举,列表,引用其他对象的属性(循环),需要到日志文件以及。
有一个更好的方法:一个通用的调试,使用反射来显示所有对象的字段和属性的作家,遍历对象图,如果有必要,并产生一些人类可读的足够的信息进行分析。这实在是一个新的想法,CodeProject上已经有转储类被创建。 使用代码
包括Dump.cs文件到您的项目,或链接完成{A3}大会。现在马车一块倾销守则以上可以换成:{C}
产生:
c = (C) { /* #1, 03553390 */

  X = (int)  5 (0x5)

  Y = (string) "Hello"

  Child = (DirectoryInfo) { /* #2, 01fed012 */

    Name = (string) "C:\"

    Parent = (DirectoryInfo) "<null>" /* ToString */

    Exists = (bool) true

    Root = (DirectoryInfo) "C:\" /* ToString */

    FullName = (string) "C:\"

    Extension = (string) ""

    CreationTime = (DateTime) 2009-03-03T08:30:17.8593750-05:00 (Local)

    CreationTimeUtc = (DateTime) 2009-03-03T13:30:17.8593750Z (Utc)

    LastAccessTime = (DateTime) 2010-04-14T00:38:01.6864128-04:00 (Local)

    LastAccessTimeUtc = (DateTime) 2010-04-14T04:38:01.6864128Z (Utc)

    LastWriteTime = (DateTime) 2010-04-13T12:22:52.3763914-04:00 (Local)

    LastWriteTimeUtc = (DateTime) 2010-04-13T16:22:52.3763914Z (Utc)

    Attributes = (FileAttributes) [Hidden, System, Directory] /* 0x00000016 */

  }

  Z = (int)  0 (0x0)

}

对象ID和哈希码输出,简化了复杂的对象图的跟踪与循环。例如,/ *#2,01fed012 * /以上是指对象的GetHashCode()= 0x01fed012#2。
也可能控制深度倾销的对象树,显示数组元素的最大数量和其他一些小东西。详情请参阅{A4}和连接的样品。特殊类型和属性
有些类有副作用的属性。例如,需要很长时间,要检索或无效对象的内部状态的属性。为了防止转储访问该等物业,物业应当予以登记Dump.AddHiddenProperty()静态方法。
此外,一些属性和类型会导致正常时倾倒太多膨胀:"Bloatquot;类型并不重要,正在调试的应用程序的类型。例如,的System.Type System.Reflection.Assembly和许多其他的运行时类有几十名市民的内部属性,对大多数应用程序开发很少使用。"Bloatquot;属性默默创建一个父对象的副本,在被访问时。这种设计的一个例子是家长和根System.IO.DirectoryInfo类的属性。 W / O的特殊待遇倾销新DirectoryInfo的("C:\ quot;)会产生quot财产根长树的嵌套对象,C:\"返回自身的新副本。
为了避免这些问题,一些已知的quot; bloatquot;类型和属性被写入转储使用ToString()方法,并显示* /输出/ *的ToString。更多quot; bloatquot;可注册类型和属性通过Dump.AddBloatProperty()和Dump.AddBloatType()方法。
这是一个好主意,在程序启动时注册的所有已知的特殊类型/属性,以避免线程问题。另一个例子有关安装CDROM驱动器
转储到控制台:
Console.WriteLine(Dump.ToDump(  

        from d in DriveInfo.GetDrives()

        where d.DriveType==DriveType.CDRom

        select d));

//----------------------------------
(WhereArrayIterator<driveinfo />) { /* #1, 02b89eaa */ 

  [0] = (DriveInfo) { /* #2, 0273e403 */ 

    Name = (string) "D:\"

    DriveType = (DriveType) [CDRom] /* 0x00000005 */

    DriveFormat = (string) "UDF"

    IsReady = (bool) true

    AvailableFreeSpace = (long)  0 (0x0)

    TotalFreeSpace = (long)  0 (0x0)

    TotalSize = (long)  6394689536 (0x17d273800)

    RootDirectory = (DirectoryInfo) { /* #3, 025f14a9 */ 

      Name = (string) "D:\"

      Parent = (DirectoryInfo) "<null />" /* ToString */

      Exists = (bool) true

      Root = (DirectoryInfo) "D:\" /* ToString */

      FullName = (string) "D:\"

      Extension = (string) ""

      CreationTime = (DateTime) 2008-04-30T16:36:29.2960000-04:00 (Local)

      CreationTimeUtc = (DateTime) 2008-04-30T20:36:29.2960000Z (Utc)

      LastAccessTime = (DateTime) 2008-04-30T16:43:12.8430000-04:00 (Local)

      LastAccessTimeUtc = (DateTime) 2008-04-30T20:43:12.8430000Z (Utc)

      LastWriteTime = (DateTime) 2008-04-30T16:43:09.2810000-04:00 (Local)

      LastWriteTimeUtc = (DateTime) 2008-04-30T20:43:09.2810000Z (Utc)

      Attributes = (FileAttributes) [ReadOnly, Directory] /* 0x00000011 */

    }

    VolumeLabel = (string) "OS_4455.01"

  }

  [1] = (DriveInfo) { /* #4, 02b6a1ca */ 

    Name = (string) "V:\"

    DriveType = (DriveType) [CDRom] /* 0x00000005 */

    DriveFormat = (string) "UDF"

    IsReady = (bool) true

    AvailableFreeSpace = (long)  0 (0x0)

    TotalFreeSpace = (long)  0 (0x0)

    TotalSize = (long)  2501894144 (0x951fe000)

    RootDirectory = (DirectoryInfo) { /* #5, 021a7086 */ 

      Name = (string) "V:\"

      Parent = (DirectoryInfo) "<null />" /* ToString */

      Exists = (bool) true

      Root = (DirectoryInfo) "V:\" /* ToString */

      FullName = (string) "V:\"

      Extension = (string) ""

      CreationTime = (DateTime) 2009-07-14T05:26:40.0000000-04:00 (Local)

      CreationTimeUtc = (DateTime) 2009-07-14T09:26:40.0000000Z (Utc)

      LastAccessTime = (DateTime) 2009-07-14T05:26:40.0000000-04:00 (Local)

      LastAccessTimeUtc = (DateTime) 2009-07-14T09:26:40.0000000Z (Utc)

      LastWriteTime = (DateTime) 2009-07-14T05:26:40.0000000-04:00 (Local)

      LastWriteTimeUtc = (DateTime) 2009-07-14T09:26:40.0000000Z (Utc)

      Attributes = (FileAttributes) [ReadOnly, Directory] /* 0x00000011 */

    }

    VolumeLabel = (string) "GRMCPRFRER_EN_DVD"

  }

}
历史
{A5}可以下载最新版本。

回答

评论会员:赛义德Saqib阿里Tipu 时间:2012/01/26
非常有用

感谢分享
评论会员:哈王 时间:2012/01/26
!好文章

感谢分享。
评论会员:TobiasP 时间:2012/01/26
KOOL