7

尝试调试以下简单程序,并x在每个步骤中将鼠标悬停(或“添加监视”x或其他)。

using System;
using System.Globalization;

static class Program
{
  static double x;

  static void Main()
  {
    x = 2d;

    // now debugger shows "2.0", as if it has used
    // x.ToString("F1", CultureInfo.InvariantCulture)

    x = 8.0 / 7.0;

    // now debugger shows "1.1428571428571428", as if it had used
    // x.ToString("R", CultureInfo.InvariantCulture)
    // Note that 17 significant figures are shown, not the usual 15.

    x = -1e-200 / 1e200;

    // now debugger shows "0.0"; there is no indication that this is really negative zero
    //

    Console.WriteLine(1.0 / x); // this is negative infinity
  }
}

因此,显然 VS 有自己的方式来显示System.Double. 它为此目的调用了哪种方法?有没有办法以编程方式获得完全相同的字符串表示?

(使用 Visual Studio 2010 Professional 进行了尝试。)

4

2 回答 2

8

C# 和 VB.Net EE 的核心都使用该_ecvt_s函数将 a 格式化double为字符串。

两者都对生成的字符串进行了一些清理,以使显示更像 C# 和 VB,并更好地处理一些极端情况。函数_ecvt_s或清理代码都可能导致您看到的差异。很难一眼看出

有些人可能会问,为什么我们会经历所有这些麻烦,而不是说只是调用ToString价值并显示它。我们不这样做有几个原因。

第一个很简单,功能评估甚至ToString是 EE 可以执行的最昂贵的操作。常见真实场景的配置文件显示,我们 98% 以上的时间都花在了功能评估上。由于性能影响,任何时候我们都可以避免 func eval。

第二个原因很简单,函数评估并不总是可用的。在许多情况下 func eval 不可用,但人们仍然希望看到原始类型的显示,如double,int等......将它们移除会基本上扼杀调试体验。因此,我们需要在没有ToString支持的情况下解决这个问题。

于 2012-04-20T19:01:39.800 回答
2

我会接受 JaredPar 的回答,因为它描述了调试器内部的工作方式。

但是因为答案无助于获得相同的字符串,所以这里有一些经常(总是?)给出相同字符串的代码:

static string ToDebugString(this double d)
{
  if (Double.IsNaN(d) || Double.IsInfinity(d))
    return d.ToString(CultureInfo.InvariantCulture);

  string s = d.ToString("R", CultureInfo.InvariantCulture);
  if (!s.Contains("."))
    s += ".0";
  return s;
}

请随时改进此答案。

于 2012-04-25T17:53:03.713 回答