practices - log de errores c#
¿Existen__LINE____FILE__ equivalentes en C#? (7)
Con Caller Information (introducido en .NET 4.5) puede crear el equivalente de __LINE__
y __FILE__
en C #:
static int __LINE__([System.Runtime.CompilerServices.CallerLineNumber] int lineNumber = 0)
{
return lineNumber;
}
static string __FILE__([System.Runtime.CompilerServices.CallerFilePath] string fileName = "")
{
return fileName;
}
Lo único que debe recordar es que estas son funciones y no directivas del compilador.
Así por ejemplo:
MessageBox.Show("Line " + __LINE__() + " in " + __FILE__());
Si usaras esto en la práctica, te sugeriría diferentes nombres. He usado los nombres de C / C ++ solo para CurrentLineNumber()
lo que están devolviendo, y algo como CurrentLineNumber()
y CurrentFileName()
podrían ser nombres mejores.
La ventaja de usar la información de llamada sobre cualquier solución que use StackTrace
es que la información de línea y archivo está disponible tanto para la depuración como para la versión.
Para fines de registro
__LINE__
__FILE__
eran mis amigos en C / C ++. En Java para obtener esa información, tuve que lanzar una excepción y atraparla. ¿Por qué estos viejos recursos están tan descuidados en los lenguajes de programación modernos? Hay algo mágico en su simplicidad.
Es más feo, pero puedes hacer algo como esto en C # usando las clases StackTrace y StackFrame :
StackTrace st = new StackTrace(new StackFrame(true));
Console.WriteLine(" Stack trace for current level: {0}", st.ToString());
StackFrame sf = st.GetFrame(0);
Console.WriteLine(" File: {0}", sf.GetFileName());
Console.WriteLine(" Method: {0}", sf.GetMethod().Name);
Console.WriteLine(" Line Number: {0}", sf.GetFileLineNumber());
Console.WriteLine(" Column Number: {0}", sf.GetFileColumnNumber());
Por supuesto, esto viene con algunos gastos generales.
Esta es una forma de obtener el número de línea: http://askville.amazon.com/SimilarQuestions.do?req=line-numbers-stored-stack-trace-C%2523-application-throws-exception
Si usa log4net, puede obtener el número de línea y el nombre del archivo en sus registros, pero:
- puede disminuir tu aplicación. actuación
- debe tener archivos .PDB junto con sus ensamblajes.
Lo más parecido a eso es el hecho de que puede crear un objeto StackTrace
y averiguar el nombre del método en la parte superior de la pila, para que pueda acercarse a la funcionalidad de la macro __FUNCTION__
.
StackTrace stackTrace = new StackTrace();
StackFrame[] stackFrames = stackTrace.GetFrames();
foreach (StackFrame stackFrame in stackFrames)
Console.WriteLine(stackFrame.GetMethod().Name);
Para reducir el costo de escribir esto a mano, y también el código de tiempo de ejecución, puede escribir un método de ayuda:
[Conditional("Debug")]
public void LogMethodName()
{
Trace.WriteLine("Entering:" + new StackTrace().GetFrame(1).GetMethod().Name);
}
Tenga en cuenta cómo obtenemos el cuadro 1, ya que el cuadro 0 sería el mismo LogMethodName
. Al marcarlo como Condicional ("Depurar"), nos aseguramos de que el código se elimine de las compilaciones de lanzamiento, que es una forma de evitar el costo del tiempo de ejecución donde no sea necesario.
Porque el seguimiento de la pila contiene la mayor parte de lo que necesita. No le dará el nombre del archivo, pero le dará el nombre de clase / método. También contiene el número de línea. No se descuida, es automático. Solo necesitas lanzar una excepción como lo haces en Java
Ya hay algunas sugerencias para lograr lo que quieres. Utilice el objeto StackTrace o mejor log4net.
En Java para obtener esa información, tuve que lanzar una excepción y atraparla.
Eso no es del todo cierto. Puedes tenerlo sin tirar excepciones, también. Echa un vistazo a log4j. Incluso registra su método y nombre de clase, sin contaminar su código con cadenas codificadas que contienen el nombre del método actual (al menos he visto esto en algunas ocasiones).
¿Por qué estos viejos recursos están tan descuidados en los lenguajes de programación modernos?
Java y C # no hacen uso (en este último caso: uso excesivo) de preprocesadores. Y creo que está bien. Abusar de los preprocesadores para hacer código ilegible es muy fácil. Y si los programadores pueden abusar de alguna técnica ... la abusarán.
Solo una nota sobre el rendimiento, que es muy probable que sea el siguiente, que aparece en su mente:
Si usa StackTrace o log4net, siempre leerá o escuchará que es lento, porque usa Reflection. Estoy usando log4net y nunca encontré el registro como cuello de botella de rendimiento. Si fuera así, puedo desactivar declarativamente (partes de) el registro, sin cambiar el código fuente. ¡Eso es pura belleza en comparación con eliminar todas las líneas de registro en el código C / C ++! (Además: si el rendimiento es un objetivo principal, usaría C / C ++ ... nunca morirá a pesar de Java y C #).
La información de llamada se ha agregado a .NET 4.5. Esto será compilado, una gran mejora sobre tener que examinar el stacktrace manualmente.
public void Log(string message,
[CallerFilePath] string filePath = "",
[CallerLineNumber] int lineNumber = 0)
{
// Do logging
}
Simplemente llámelo de esta manera, el compilador completará el nombre del archivo y el número de línea por usted:
logger.Log("Hello!");