2012-04-20 14 views
7

Pruebe a depurar el siguiente programa simple y pase el mouse sobre x en cada paso (o "Agregar reloj" para x o lo que sea).¿Cómo muestra Visual Studio un System.Double durante la depuración?

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 
    } 
} 

Así que, al parecer VS tiene su propia manera de mostrar un System.Double. ¿Qué método llama para este propósito? ¿Hay alguna manera de obtener la misma representación de cadena programáticamente?

(intentado hacer esto con Visual Studio 2010 Professional.)

Respuesta

8

En su esencia tanto el C# y VB.Net uso de la función de EE _ecvt_s para dar formato a un double en una cadena.

Ambos hacen un poco de limpieza en la cadena resultante para hacer la pantalla más C# y VB similares y manejar algunos casos de esquina un poco más agradable. O la función _ecvt_s o el código de limpieza podrían ser responsables de las diferencias que veas. Difícil de ver de un vistazo

Algunos pueden preguntar por qué tendríamos que pasar por todos estos problemas en lugar de decir simplemente llamando al ToString en el valor y mostrar eso. Hay un par de razones por las que no hacemos esto.

La primera es simplemente que la evaluación de funciones, incluso ToString, es la acción más costosa que puede emprender EE. Los perfiles de escenarios reales comunes muestran que más del 98% de nuestro tiempo lo pasamos haciendo evaluación de funciones. En cualquier momento podemos evitar una evaluación funcional que hacemos debido a las implicaciones de rendimiento.

La segunda razón es simplemente que la evaluación de la función no siempre está disponible. Hay una serie de casos en los que la función no está disponible, pero la gente todavía espera ver una pantalla para tipos primitivos como double, int, etc ... Quitárselos esencialmente mataría la experiencia de depuración. Por lo tanto, necesitamos resolver este problema sin el soporte ToString.

+0

Respuesta muy informativa. Pero realmente no dice mi ** cómo se llama ** '_ecvt_s'. Y sospecho que los métodos 'ToString' también funcionan al llamar eventualmente a' _ecvt_s'? Además, agregar la parte ".0" a la cadena probablemente se haga por lo que usted llama el código de limpieza, por lo que llamar a '_ecvt_s' mediante algún método' extern' no haría el trabajo solo. Entonces, tal vez la respuesta es simple: No, no puedo obtener la misma cadena programáticamente. –

+0

@JeppeStigNielsen no está muy seguro de lo que quiere decir con cómo se llama _ecvt_s. ¿Podrías elaborar? En cuanto a obtener exactamente la misma cadena usted mismo, sí, es difícil de replicar a menos que tenga el código de limpieza exacto a mano. – JaredPar

+0

No estoy seguro de cómo la salida de '_ecvt_s' depende de los parámetros, como' _SizeInBytes', y '_Count'. Pero la cadena mostrada por VS parece incluir siempre al menos un dígito a la derecha del punto decimal, pero de otra manera no tiene ceros finales. La razón por la que hacen el ".0 "es cierto que deja en claro que no es un' Int32' sino un 'Doble'. –

1

Aceptaré la respuesta de JaredPar ya que describe cómo funcionan las cosas dentro del depurador.

Pero debido a que la respuesta no ayuda a conseguir la misma cadena, aquí hay un código que a menudo (siempre?) Da la misma cadena:

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; 
} 

No dude en mejorar esta respuesta.

Cuestiones relacionadas