在 C# 中使用 #define 的真实示例

本文关键字:真实 #define | 更新日期: 2023-09-27 18:29:39

我知道C#中的#define允许您定义一个符号,用作传递给#if指令的表达式,并且表达式的计算结果将true

但是我想不出这个功能有什么真正的用途,有谁知道它的真正用途吗?

在 C# 中使用 #define 的真实示例

它根本没有太多用途。

使用 #define 时,您只能为条件编译定义常量,并且通常可以通过 Build 配置来控制这些常量。

编译

时符号最常见的用法是DEBUG,默认情况下,它通过调试构建配置定义,而不是使用 #define 语句。实际上,我看到的所有编译时符号都是通过构建配置定义的。

这主要是由于源文件在 C# 中的结构方式。在C++中,某些头文件 (.h( 通常包含大量 #defines,用于与平台相关的配置。C# 不支持将文件包含在源文件中。此外,.NET 的(在很大程度上(独立于平台的性质消除了编译C++代码所需的大量定义。

此外,使用 #define 声明的符号的范围仅限于它所在的源文件。在整个项目中有效使用符号需要在使用它的所有文件中重复#define,因此很难保持一致性。

正如Henk Holterman已经指出的那样,定义全局编译时符号的唯一可维护方法是通过构建配置,因为这些符号定义一次,可用于项目中的所有文件。

话虽如此,#define验证条件编译是否按预期工作非常有用。如果在 Visual Studio 中.cs文件的顶部设置#define,则活动代码将突出显示,非活动代码将灰显。您还可以使用它在单个文件中启用仅调试代码,例如在解决问题时。

因此,要回答您的问题,据我所知,C# 中的 #define 语句在生产代码中没有很好的用途,但它可以成为方便的测试工具。

#if DEBUG
    var jwriter = new VerboseJsonWriter(0);
#else
    var jwriter = new TerseJsonWriter();
#endif

第一个以漂亮的方式格式化 JSON,包括缩进、新行中的所有内容等。以便调试时是人类可读的。

第二个将所有内容放在一行中,没有任何空格,以便在生产中最佳地使用带宽并快速加载。

你可以在代码中有一个调试记录器,你不想在发布代码中使用,所以你应该使用#define

#if DEBUG_LOG
DebuggingTool.Activate();
#else
DebuggingTool.Deactivate();
#endif

在VS 2010中,您可以在构建选项卡上添加conditional compilation symbols添加全局符号

我可以给你一个警告,为什么不使用它。

如果您使用像 resharper 这样允许重命名的工具,如果变量等位于当前配置未使用的块中,则不会重新命名变量等,但一切都会编译。

因此,如果对某些代码执行重构,该代码具有在调试中应用的条件,然后在所有内容都已编译时将其签入,这并不意味着代码将以另一种模式(如发布(编译。

这可能不是世界末日,因为你的构建服务器(应该(会捡起它,但众所周知,破坏构建意味着你欠团队其他成员啤酒!

#define作为直接插入 C# 源文件中的预处理器指令没有多大用处。您可以通过以下方式设置一个预处理变量:

#define PRO_VERSION

然后,如果你想有两个版本的应用程序(一个PRO付费版本和一个免费版本(,你可以使用prepocessor指令封装保留给PRO版本的代码#if PRO_VERSION

...
#if PRO_VERSION 
    SomethingOnlyInProVersion(); 
#elif
    SomethingOnlyInFreeVersion(); 
#endif 
...

#if PRO_VERSION 
public void SomethingOnlyInProVersion()
{
}
#elif
public void SomethingOnlyFreeVersion()
{
}
#endif 

但所有这些都将功亏一篑。如果要在没有PRO_VERSION的情况下编译代码,则需要删除#define,因为无法像旧 C 编译器那样分配值(如 #define PRO_VERSION = 0 .该指令的另一个问题是它的可见性。范围仅限于当前文件。VisualStudio引入Configuration Manager只是为了解决这类问题。在那里,您可以创建不同的Configurations其中每个都有自己的一组符号,可以检查这些符号并将其应用于整个解决方案或单个项目,而无需接触源文件。

我只有一个合法的用途,那就是具有Conditional属性的单元测试方法:

public class Foo()
{
    [Conditional("XYZ")]
    public void Bar()
    {
        // Something cool...
    }
}

我必须添加 #define 指令才能对该方法进行单元测试:

#define XYZ
public class FooTests
{
    [Test]
    public void BarShouldDoSomethingCool()
    {
        var subject = new Foo();
        subject.Bar();
        // assert something cool happened
    }
}

如果没有 #define 指令,就不会在单元测试中调用该方法,从而导致测试不确定或失败。