预处理器中的 C# 宏定义

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/709463/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-04 14:18:00  来源:igfitidea点击:

C# Macro definitions in Preprocessor

c#macrosc-preprocessor

提问by

Is C# able to define macros as is done in the C programming language with pre-processor statements? I would like to simplify regular typing of certain repeating statements such as the following:

C# 是否能够像在 C 编程语言中使用预处理器语句那样定义宏?我想简化某些重复语句的常规输入,例如:

Console.WriteLine("foo");

采纳答案by Andrew Hare

No, C# does not support preprocessor macros like C. Visual Studio on the other hand has snippets. Visual Studio's snippets are a feature of the IDE and are expanded in the editor rather than replaced in the code on compilation by a preprocessor.

不,C# 不支持像 C 这样的预处理器宏。另一方面,Visual Studio 有代码。Visual Studio 的代码段是 IDE 的一项功能,在编辑器中进行扩展,而不是在编译时由预处理器在代码中替换。

回答by Anton Gogolev

Luckily, C# has no C/C++-style preprocessor - only conditional compilation and pragmas (and possibly something else I cannot recall) are supported. Unfortunatelly, C# has no metaprogramming capabilities (this mayactually relate to your question to some extent).

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

回答by Robert

Turn the C Macro into a C# static method in a class.

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

回答by Milan Jaric

I would suggest you to write extension, something like below.

我建议您编写扩展程序,如下所示。

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

Hope this helps (and not too late :) )

希望这会有所帮助(不要太晚:))

回答by anthonybell

I use this to avoid Console.WriteLine(...):

我用它来避免Console.WriteLine(...)

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

and then you can use the following:

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

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

it's concise and kindof funky.

它简洁而有点时髦。

回答by user2224389

You can use a C preprocessor (like mcpp) and rig it into your .csproj file. Then you chnage "build action" on your source file from Compile to Preprocess or whatever you call it. Just add BeforBuildto your .csproj like this:

您可以使用 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>

You may have to manually change Compile to Preprocess on at least one file (in a text editor) - then the "Preprocess" option should be available for selection in Visual Studio.

您可能必须在至少一个文件(在文本编辑器中)手动更改编译为预处理 - 然后“预处理”选项应该可以在 Visual Studio 中选择。

I know that macros are heavily overused and misused but removing them completely is equally bad if not worse. A classic example of macro usage would be NotifyPropertyChanged. Every programmer who had to rewrite this code by hand thousands of times knows how painful it is without macros.

我知道宏被严重过度使用和误用,但完全删除它们即使不是更糟也同样糟糕。宏用法的一个经典示例是NotifyPropertyChanged。每个不得不手动重写此代码数千次的程序员都知道没有宏是多么痛苦。

回答by Binkan Salaryman

There is no direct equivalent to C-style macros in C#, but inlined static methods - with or without #if/#elseif/#elsepragmas - is the closest you can get:

没有直接等价于C风格的宏在C#中,但inlined静态方法-用或不用#if/ #elseif/#else编译指示-是你可以得到的最接近:

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

This works perfectly as a macro, but comes with a little drawback: Methods marked as inlined will be copied to the reflection part of your assembly like any other "normal" method.

这作为宏完美运行,但有一个小缺点:标记为inlined 的方法将像任何其他“正常”方法一样复制到程序集的反射部分。

回答by sraboy

While you can't write macros, when it comes to simplifying things like your example, C# 6.0 now offers static usings. Here's the example Martin Pernica gave on his Medium article:

虽然您无法编写宏,但在简化示例时,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;
    }
  }
}

回答by moien

Since C# 7.0 supports using staticdirective and Local functionsyou don't need preprocessor macros for most cases.

由于 C# 7.0 支持using static指令和本地函数,因此在大多数情况下您不需要预处理器宏。

回答by moien

I will create a C# macrocompiler called C#macros.

我将创建一个名为 C#macros 的 C# 宏编译器。

Progress is here.

进步就在这里