【问题标题】:Issues with using #ifdefs in C#在 C# 中使用 #ifdefs 的问题
【发布时间】:2015-10-07 14:04:04
【问题描述】:

我有使用这种方法的 C++ 代码:

#if defined(CONSTANT)
..
// Some code
#else
// Some other code

有人告诉我,我可以在 C# 中使用类似的方法——因为我需要将此 C++ 项目重写为 C#。 但是有一个问题。从我在 C# 中看到的文档中,如果我使用

#define CONSTANT

这仅在声明它的文件中可见。

但我不想要这个。我希望这个CONSTANT 在所有课程中都可见吗? 我认为一个解决方案是在项目设置等中声明此类常量 - 但这是我的第一个问题:在这种情况下,我是否需要使用我的 DLL 发送一些额外的文件?或者这些常量会被嵌入到 DLL 中?

最后,为了避免上述问题,我正在考虑在 C# 中仅使用公共 const 值的方法。喜欢

if(Globals.SomeConstant == SOMEVALUE)
// Do this
else
// Do smth else

然后根据配置,我将在Globals.SomeConstant 声明期间将默认值设置为我需要的值,编译 DLL 并发送它。这听起来不错,它会像这样工作吗?是否会在 DLL 方法中正确分配和读取默认值? (他们会像 #ifdefs 那样工作吗?)

我知道我需要重新编译才能更改代码,但这没关系。

【问题讨论】:

  • 您可以在该项目的项目属性中定义全局定义。 Properties>Build>Conditional Compilation Symbols 那里定义的符号不会被嵌入,编译后的代码将在编译器中遵循不同的路径,编译符号是“编译时”的东西,而不是运行时。您发布的第二种方法不等同于#ifdef,我会避免这种方法。
  • 它们只是编译时常量,不会嵌入到您的 DLL 中。
  • @RonBeyer:我的意思是,如果我在项目属性中定义了你提到的那些常量,我是否需要在我的 DLL 中附加任何东西?或者只是我的 DLL 就可以了?并且根据我在属性中定义的符号,我可以适当地使用#ifdefs 吗?
  • DLL 将是您需要发送的所有内容,代码将根据符号是否定义而不同地编译。这是对符号的适当使用,用于定义仅在定义该符号时才编译的代码。
  • @RonBeyer:好的,所以我应该检查属性->构建等?公共常量方法有什么问题

标签: c# c++ dll


【解决方案1】:

C# 不像 C/C++ 那样具有“预处理器”。这些#defines 也不是“常量”——它们只是“符号”,您只能查询存在或不存在。它们在编译的程序集中不会留下任何痕迹。

现在,当您使用(或不使用)#defined 符号编译程序集时,结果很可能会有所不同:

public const int I =
#if FOO_BAR
    42
#else
    43
#endif
;

在#defines 方面,C/C++ 和 C# 之间的概念区别在于 C/C++ 中的库通常以源代码形式分发,并且在与您自己的代码一起编译时,遵循全局 #defines。另一方面,在 C# 中,第三方代码最常作为编译程序集分发。因此,如果您想更改此第三方程序集中代码的工作方式,则必须在运行时执行此操作。

【讨论】:

  • “另一方面,在 C# 中,第三方代码通常作为已编译的程序集分发。因此,如果您想更改此第三方程序集中代码的工作方式,您可以必须在运行时执行此操作。” -- 你能解释一下你的意思吗?
【解决方案2】:

如果您使用的是 Visual Studio,那么做预处理器指令非常简单。

  1. 选择项目
  2. 属性
  3. 构建
  4. 在“条件编译符号”上放置您想要的符号,您应该可以访问所有程序集

如果您不使用 Visual Studio,请关注 this topic。

为了了解预处理器指令,您可以访问Tutorialspoint C# 网站。

要使用 C++ 方法在 C# 中编写代码,您可以使用以下语法:

#define Name_Value

#if (Name_value)
{
   //code
}

如果这不符合您的需求,您可以使用配置文件,您可以在其中堆叠所有键名 - 值并通过 ConfigurationManger.AppSettings["Key"] 访问它们

解决此问题的另一种方法是使用全局 enum 并分配值。

 public enum DemoEnum
 {
     Name = Value
 } 

 if(passedEnum == DemoEnum.Name)
 {
     // code
 }

您使用常量提供的解决方案不是很灵活,因为如果您的代码更改,您将不得不创建新的常量并且图像变得太模糊。

使用只读属性,您可以在方法中切换 'const' 的值。

public class Global
{
    public readonly string Name;

    public Global()
    {
        if(condition)
           Name = 10;
        else
           Name = 30;
    }
}

如果我忘记了选项,请随时发表评论:)

【讨论】:

  • " 你用常量给出的解决方案不是很灵活,因为如果你的代码发生变化,你将不得不创建新的常量并且图像变得太模糊。" - 你能解释一下你的意思吗?我正在考虑公共常量,因为如果需要重新编译这不是问题,因为当前的 C++ 解决方案也可以这样工作。你怎么看?
  • 有人告诉我“但请注意:不能保证您的解决方案中的所有项目的条件编译符号都相同。这将阻碍其他需要不同条件的解决方案重用您的 DLL编译符号。” - 你知道这意味着什么吗?
  • 我的意思基本上是一个全局常量枚举
  • @user300224 全局枚举就像一个魅力,但你必须知道要测试什么值,正如你在你的问题中指出的那样 if(Globals.SomeConstant == SOMEVALUE) // Do this else // 做别的事
  • Bodgan:是的,请看这里public const DppConfiguration configuration = DppConfiguration.SOFTWARE_HSM; - DppConfiguration - 是一个枚举。如您所见,我在声明时给出了一些初始值。即使在 DLL 中也能正常工作吗?请对此发表评论。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2012-05-23
  • 2010-12-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多