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大师)
#有效地定义宏
在每个源中创建一个新关键字
文件和每个作用域,直到该符号
是#未定义的
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() {}
}