C# 引用:预处理器的使用是不好的OO实践

C# 引用:预处理器的使用是不好的OO实践,c#,oop,c-preprocessor,dos-donts,C#,Oop,C Preprocessor,Dos Donts,我相信,使用诸如#if UsingNetwork之类的预处理器指令是不好的OO实践,其他同事则不然。 我认为,当使用IoC容器(例如Spring)时,如果进行相应编程,则可以轻松配置组件。在这种情况下,IoC容器可以设置属性IsUsingNetwork,或者,如果“using network”实现的行为不同,则应该实现并注入该接口的另一个实现(例如:iSeries设备,ServiceImplementation,NetworkingServiceImplementation) 是否有人可以提供O

我相信,使用诸如
#if UsingNetwork
之类的预处理器指令是不好的OO实践,其他同事则不然。 我认为,当使用IoC容器(例如Spring)时,如果进行相应编程,则可以轻松配置组件。在这种情况下,IoC容器可以设置属性
IsUsingNetwork
,或者,如果“using network”实现的行为不同,则应该实现并注入该接口的另一个实现(例如:
iSeries设备
ServiceImplementation
NetworkingServiceImplementation

是否有人可以提供OO大师的引用或书籍中的参考资料,这些书基本上是这样写的:“如果你试图配置行为,那么预处理器的使用是不好的OO实践,应该通过IoC容器进行配置”

我需要这些引文来说服同事重构…

编辑:我知道并同意在编译过程中使用预处理器指令更改特定于targetplatform的代码是可以的,这就是预处理器指令的用途。然而,我认为应该使用运行时配置而不是compiletime配置来获得设计良好且可测试的类和组件。换句话说:使用#定义和#如果超出了它们的用途,将导致难以测试代码和设计糟糕的类

有没有人读过类似的东西,能给我一些参考

“预处理器是邪恶的化身,是地球上所有痛苦的根源”-罗伯特(OO大师)


,你谈论的是C和C++,而不是一般的OO实践。C不是面向对象的。在这两种语言中,预处理器实际上都很有用。只要正确使用它

我认为这个答案属于我

是的,这正是我要说的: 预处理器是邪恶的

每个
#有效地定义
宏
在每个源中创建一个新关键字
文件和每个作用域,直到该符号
是
#未定义的
d。预处理器允许 您创建了一个#define符号 始终独立于
{…}
符号所在的范围 出现了

有时我们需要预处理器, 例如
#ifndef/#define
包装器 在每个头文件中,但它应该 尽量避免。“邪恶” 这并不意味着“永远不用”,你会用的 邪恶的事情有时会发生,尤其是 当他们是“两个中的较小者” 邪恶。“但它们仍然是邪恶的:-)


我希望这个源代码足够权威:-)

在C#中对预处理的支持非常少。。。。快要没用了。那是邪恶的吗

预处理器与OO有关吗?当然,这是为了构建配置

例如,我的应用程序有一个lite版本和一个pro版本。我可能想排除lite上的一些代码,因为我们必须构建非常相似的代码版本


我可能不想发布一个lite版本,它是具有不同运行时标志的pro版本

托尼

在c#/VB.NET中,我不会说它是邪恶的

例如,在调试windows服务时,我将以下内容放在Main中,以便在调试模式下,可以将服务作为应用程序运行

    <MTAThread()> _
    <System.Diagnostics.DebuggerNonUserCode()> _
    Shared Sub Main()


#If DEBUG Then

        'Starts this up as an application.'

        Dim _service As New DispatchService()
        _service.ServiceStartupMethod(Nothing)
        System.Threading.Thread.Sleep(System.Threading.Timeout.Infinite)

#Else

        'Runs as a service. '

        Dim ServicesToRun() As System.ServiceProcess.ServiceBase
        ServicesToRun = New System.ServiceProcess.ServiceBase() {New DispatchService}
        System.ServiceProcess.ServiceBase.Run(ServicesToRun)

#End If

    End Sub

C#中的预处理器指令具有非常清晰的定义和实际用例。您特别提到的那些称为条件指令的指令,用于控制代码的哪些部分被编译,哪些部分未被编译

不编译部分代码和通过IoC控制对象图的连接方式之间有一个非常重要的区别。让我们看一个真实的例子:XNA。当您正在开发计划同时部署在Windows和XBox 360上的XNA游戏时,您的解决方案通常会在IDE中至少有两个平台可供切换。它们之间存在一些差异,但其中一个差异是XBox 360平台将定义一个条件符号XBox 360,您可以在源代码中使用以下习惯用法:

#if (XBOX360)
// some XBOX360-specific code here
#else
// some Windows-specific code here
#endif
当然,您可以使用策略设计模式并通过IoC控制实例化哪一个来消除这些差异,但条件编译至少提供了三个主要优势:

  • 你不需要发送你不需要的代码
  • 在代码的正确上下文中,您可以看到两个平台的特定于平台的代码之间的差异
  • 没有间接开销。适当的代码已编译,另一个未编译,仅此而已

  • 在国际海事组织,区分“如果”和“定义”很重要。两者都可能有用,也可能被过度使用。我的经验是,define比if更可能被过度使用

    我花了10年的时间做C和C++编程。在我所从事的项目中(针对DOS/Unix/Macintosh/Windows的商用软件),我们主要使用“if”和“define”来处理代码可移植性问题

    <> P>我花了足够的时间与C++/MFC一起学习,当它被过度使用时,学会讨厌定义。我相信MFC CycCA 1996中的情况是这样的。

    然后我花了7年多的时间在Java项目上工作。我不能说我错过了预处理器(尽管我确实错过了Java当时没有的枚举类型和模板/泛型)

    我从2003年起一直在C#工作。我们在调试构建中大量使用了#if和[Conditional(“DEBUG”)]——但是#if只是一种更方便、更高效的方法,它与我们在Java中做的事情一样

    接下来,我们已经开始准备Silverlight的核心引擎。虽然我们正在做的每件事都可以不用#if完成,但对#if的工作更少,这意味着我们可以花更多时间添加客户要求的功能。例如,我们有一个值类,它封装了一个系统列
    #if (XBOX360)
    // some XBOX360-specific code here
    #else
    // some Windows-specific code here
    #endif
    
    using System;
    using System.Collections.Generic;
    using System.Text;
    using System.Diagnostics;
    #if SILVERLIGHT
    using SystemColor = System.Windows.Media.Color;
    #else
    using SystemColor = System.Drawing.Color;
    #endif
    
    namespace SpreadsheetGear.Drawing
    {
        /// <summary>
        /// Represents a Color in the SpreadsheetGear API and provides implicit conversion operators to and from System.Drawing.Color and / or System.Windows.Media.Color.
        /// </summary>
        public struct Color
        {
            public override string ToString()
            {
                //return string.Format("Color({0}, {1}, {2})", R, G, B);
                return _color.ToString();
            }
    
            public override bool Equals(object obj)
            {
                return (obj is Color && (this == (Color)obj))
                    || (obj is SystemColor && (_color == (SystemColor)obj));
            }
            ...
    
      #ifdef DEBUG
      //...
      #else
      //...
    
      #ifdef MANUALLY_MANAGED_MEMORY
      ...
    
    #define A
    #undef B
    class C
    {
    #if A
       void F() {}
    #else
       void G() {}
    #endif
    #if B
       void H() {}
    #else
       void I() {}
    #endif
    }
    
    class C
    {
       void F() {}
       void I() {}
    }