preprocesamiento - Definiciones de macros de C#en el preprocesador
funcion preprocesador en c++ (9)
Afortunadamente, C # no tiene preprocesador de estilo C / C ++, solo se admiten la compilación condicional y los pragmas (y posiblemente algo más que no puedo recordar). Desafortunadamente, C # no tiene capacidades de metaprogramación (esto puede estar relacionado con su pregunta hasta cierto punto).
¿Es capaz C # de definir macros como se hace en el lenguaje de programación C con declaraciones del preprocesador? Me gustaría simplificar la escritura regular de ciertas declaraciones repetitivas como las siguientes:
Console.WriteLine("foo");
Como C # 7.0 admite el using static
directivas using static
y funciones locales , no necesita macros de preprocesador para la mayoría de los casos.
Convierta la macro C en un método estático C # en una clase.
No hay un equivalente directo a las macros de estilo C en C #, pero los métodos estáticos en inline
- con o sin #if
/ #elseif
/ #else pragmas - es lo más cercano que puede obtener:
/// <summary>
/// Prints a message when in debug mode
/// </summary>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static unsafe void Log(object message) {
#if DEBUG
Console.WriteLine(message);
#endif
}
/// <summary>
/// Prints a formatted message when in debug mode
/// </summary>
/// <param name="format">A composite format string</param>
/// <param name="args">An array of objects to write using format</param>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static unsafe void Log(string format, params object[] args) {
#if DEBUG
Console.WriteLine(format, args);
#endif
}
/// <summary>
/// Computes the square of a number
/// </summary>
/// <param name="x">The value</param>
/// <returns>x * x</returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static double Square(double x) {
return x * x;
}
/// <summary>
/// Wipes a region of memory
/// </summary>
/// <param name="buffer">The buffer</param>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static unsafe void ClearBuffer(ref byte[] buffer) {
ClearBuffer(ref buffer, 0, buffer.Length);
}
/// <summary>
/// Wipes a region of memory
/// </summary>
/// <param name="buffer">The buffer</param>
/// <param name="offset">Start index</param>
/// <param name="length">Number of bytes to clear</param>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static unsafe void ClearBuffer(ref byte[] buffer, int offset, int length) {
fixed(byte* ptrBuffer = &buffer[offset]) {
for(int i = 0; i < length; ++i) {
*(ptrBuffer + i) = 0;
}
}
}
Esto funciona perfectamente como una macro, pero tiene un pequeño inconveniente: los métodos marcados como en inline
d se copiarán a la parte de reflexión de su ensamblaje como cualquier otro método "normal".
No, C # no admite macros de preprocesador como C. Visual Studio por otro lado tiene snippets . Los fragmentos de Visual Studio son una característica del IDE y se expanden en el editor en lugar de ser reemplazados por el preprocesador en el código de la compilación.
Puede usar un preprocesador de C (como mcpp) y colocarlo en su archivo .csproj. Luego cambia la "acción de compilación" en su archivo fuente desde Compilar a Preproceso o como se llame. Solo agrega BeforBuild a tu .csproj de esta manera:
<Target Name="BeforeBuild" Inputs="@(Preprocess)" Outputs="@(Preprocess->''%(Filename)_P.cs'')">
<Exec Command="../Bin/cpp.exe @(Preprocess) -P -o %(RelativeDir)%(Filename)_P.cs" />
<CreateItem Include="@(Preprocess->''%(RelativeDir)%(Filename)_P.cs'')">
<Output TaskParameter="Include" ItemName="Compile" />
</CreateItem>
Es posible que tenga que cambiar manualmente Compilar a Preproceso en al menos un archivo (en un editor de texto); luego, la opción "Preproceso" debe estar disponible para su selección en Visual Studio.
Sé que las macros son muy utilizadas en exceso y mal utilizadas, pero eliminarlas por completo es igualmente malo, si no peor. Un ejemplo clásico de uso de macros sería NotifyPropertyChanged . Cada programador que tuvo que volver a escribir este código a mano miles de veces sabe lo doloroso que es sin macros.
Si bien no puede escribir macros, cuando se trata de simplificar cosas como su ejemplo, C # 6.0 ahora ofrece usos estáticos. Aquí está el ejemplo que dio Martin Pernica en su artículo de Medium :
using static System.Console; // Note the static keyword
namespace CoolCSharp6Features
{
public class Program
{
public static int Main(string[] args)
{
WriteLine("Hellow World without Console class name prefix!");
return 0;
}
}
}
Te sugiero que escribas una extensión, algo como abajo.
public static class WriteToConsoleExtension
{
// Extension to all types
public static void WriteToConsole(this object instance,
string format,
params object[] data)
{
Console.WriteLine(format, data);
}
}
class Program
{
static void Main(string[] args)
{
Program p = new Program();
// Usage of extension
p.WriteToConsole("Test {0}, {1}", DateTime.Now, 1);
}
}
Espero que esto ayude (y no demasiado tarde :))
Uso esto para evitar Console.WriteLine(...)
:
public static void Cout(this string str, params object[] args) {
Console.WriteLine(str, args);
}
y luego puedes usar lo siguiente:
"line 1".Cout();
"This {0} is an {1}".Cout("sentence", "example");
Es conciso y algo funky.