预处理器中的C#macros定义

C#能够像使用预处理器语句的C编程语言那样定义macros吗? 我想简化某些重复语句的常规input,如下所示:

Console.WriteLine("foo"); 

不,C#不支持像C这样的预处理macros。另一方面,Visual Studio有片段 。 Visual Studio的片段是IDE的一个特性,在编辑器中进行了扩展,而不是在预编译器编译的代码中进行replace。

我用这个来避免Console.WriteLine(...)

 public static void Cout(this string str, params object[] args) { Console.WriteLine(str, args); } 

然后您可以使用以下内容:

 "line 1".Cout(); "This {0} is an {1}".Cout("sentence", "example"); 

它简洁而又时髦。

您可以使用C预处理器(如mcpp)并将其安装到.csproj文件中。 然后你从你的源代码文件中编译“预处理”或者你所说的任何东西。 只需将BeforBuild添加到您的.csproj中,如下所示:

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

您可能必须在至less一个文件(在文本编辑器中)手动将编译更改为预处理,然后在Visual Studio中select“预处理”选项。

我知道macros被过度使用和滥用,但是彻底删除它们同样糟糕,如果不是更糟的话。 macros使用的典型例子是NotifyPropertyChanged 。 每个程序员必须手工重写这个代码几千次才知道没有macros是多么的痛苦。

虽然不能编写macros,但是在简化例如C#时,C#6.0现在提供静态使用。 以下是Martin Pernica在他的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; } } } 

在C#中没有直接等价于C风格的macros,但inline d静态方法 – 有或没有#if / #elseif / #else #elseif – 是最接近你可以得到的:

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

这是一个完美的macros,但有一个小缺点:标记为inline d的方法将被复制到您的程序集的reflection部分像任何其他“正常”的方法。

幸运的是,C#没有C / C ++风格的预处理器 – 只支持条件编译和编译指示(可能还有别的我不记得的东西)。 不幸的是,C#没有元编程能力(这在某种程度上实际上可能与你的问题有关)。

将Cmacros转换为类中的C#静态方法。

我build议你写延伸,如下所示。

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

希望这有助于(而不是太迟:))