IRONSOFTWAREHOME

重构 C# 中的条件 if:与 Derek Comartin 一起避免条件混乱

[[academy-video-youtube({"vid":"QoK7jSZ-viw", "start_time":"0", "title":"枚举并不邪恶。 处处有条件,"创作者": "Derek Comartin", "长度": "11分03秒"})]]

在 C# 中,if 语句、if else 语句和 switch 语句等条件语句是必不可少的工具。 但是,如果过度使用这些构造,尤其是与枚举绑定时,会发生什么情况呢? Derek Comartin 在他的视频"枚举并不邪恶。 条件无处不在》通过详细的重构,用更简洁、可维护性更强的模式取代了普遍存在的条件逻辑。

在本文中,我们将以 Derek 的时间戳为锚,一步一步地进行推理。 我们还将探讨他的观点如何应用于 C# 中的常见条件模式,如三元运算符、else 语句和 switch-case 结构--强调这些在大型代码库中可能导致问题的地方,以及如何重构以实现更好的设计。

条件 If 爆炸:真正的问题

Derek 首先展示了检查产品类型的 if 语句:

if (productType == ProductType.Template || productType == ProductType.Ebook)

乍一看,上面的条件 if 简单明了。 但 Derek 警告说,这种语句会对给定条件进行评估,然后仅在条件为真的情况下执行代码块--如果这种逻辑到处重复,就会出现问题。

您可能会在另一个方法或类中再次遇到这个块:

if (offeringType == ProductType.Template || offeringType == ProductType.Ebook)

Derek 解释说,这种模式很快就会在大型系统中传播开来。 多个服务中出现了相同的 if else 逻辑,导致在添加新枚举值时出现不一致和错误。 例如,当您引入一个新的产品类型(如视频)时,会发生什么情况? 您必须记住更新存在此条件表达式的每一个代码块。

重复会增加复杂性

在下面的示例中,Derek 深入探讨了嵌套条件式。 在一个方法中,if else 语句检查相同的枚举,然后将结果传递给另一个方法,后者也包含类似的检查。

语句检查模板或 Ebook,并返回内容,否则返回空。 Derek 指出,这种冗余不仅会使代码变长,还会带来维护方面的隐患。 相同的逻辑被复制到多个文件中,导致控制流混乱。

如果您的系统要求您在每次接触枚举时都添加默认情况,那么您就知道有问题了。

改变我们思考条件句的方式

Derek 建议提出一个更好的问题,而不是不断地用 if else 检查类型:

产品是否具有可下载的特性?

这样才能更好地表达意图。 它使您的代码更具可读性,并减少对枚举的完全依赖。 而不是写一个包含两个条件的 if 语句,如

if (product.Type == ProductType.Template || product.Type == ProductType.Ebook)

您只需将该逻辑封装在一个模型中并编写即可:

if (product.HasDownloadableResource())

只有当存在可下载资源时,翻译才会返回真实内容,从而减少对复杂条件表达式的需求。

从 If 语句到封装行为

为了解决核心问题,Derek 引入了可下载资源类型。 该类型包括下载 URL 和默认文件名。 它将成为您领域的一流组成部分,而不是依靠 if 语句来推导。

现在,我不再重复这些了:

if (product.Type == ProductType.Template)
{
    // Generate file name
}
else if (product.Type == ProductType.Ebook)
{
    // Generate file name
}

你来写

var downloadable = product.GetDownloadableResource();
if (downloadable != null)
{
    Console.WriteLine(downloadable.FileName);
}

在翻译过程中,翻译人员必须使用.NET、Java、Python 或 Node js 等开发工具,这样可以大大简化逻辑,不需要 else 语句分支,甚至不需要 switch 语句。

运行时重于编译时:战略转移

Derek 进一步解释了一个重要的设计选择:将逻辑从编译时转移到运行时。这意味着要在运行时查询系统,查看产品是否存在可下载资源。 如果可以,就请付诸行动。 否则,请跳过。

他指出,此举将静态的 if else 逻辑转化为运行时查询。 它可能会增加数据库调用,但会减少嵌套的 if else 逻辑并集中行为。 这样可以提高大规模的可维护性。

为可下载产品使用继承

德里克探索的另一条途径是继承。 您可以创建一个抽象基类 Product,然后定义派生类型,如 Ebook、Template 或 OfflineCourse。

每一个都要覆盖以下方法

public virtual string GetDownloadUrl() { ... }

这种方法允许每个产品处理自己的逻辑。 虽然这避免了 switch 语句或多个条件语句,但 Derek 指出,如果您不小心,最终还是会在内部编写条件表达式。

无需继承即可实现更好的封装

如果感觉继承过于繁琐,Derek 建议使用像 DownloadableProduct 这样的显式类型,它包含自己的属性和方法,而不受制于层次结构。

在您的程序中,这可能是这样的

var downloader = new DownloadableProduct(product);
Console.WriteLine(downloader.GetDefaultFileName());

不需要 if else 或 switch 语句来确定行为--每个对象都知道该做什么。

轻量级修复:枚举上的扩展方法

如果您还没有准备好放弃枚举,Derek 会提出一个轻量级的解决方案--创建一个扩展方法:

public static bool IsDownloadable(this ProductType type)
{
    return type == ProductType.Template || type == ProductType.Ebook;
}

现在不用写

if (product.Type == ProductType.Template || product.Type == ProductType.Ebook)

您可以将其简化为

if (product.Type.IsDownloadable())

这样可以集中逻辑,避免重复大括号和代码块。

避免过度使用三元操作符和开关

Derek 还提醒大家不要过度使用三元运算符等速记符号:

string filename = product.Type == ProductType.Template ? "template.pdf" : "default.pdf";

虽然这是有效的语法,但当逻辑变得复杂时,可能会容易出错,而且难以阅读。 特别是当您的条件评估为 false 时,可能会以微妙的方式分配错误的值。

同样,带有 break 语句和默认情况的 switch 也会落入这个陷阱。与其使用 switch-case 逻辑,不如询问对象的行为。

结论:用更少的杂乱条件实现更智能的控制

总之,Derek 的视频并不是对枚举的攻击,而是对我们如何围绕枚举使用条件 if 结构的批评。 在代码库中散布 if else 和 switch 语句会增加系统的测试、维护和发展难度。

无论您是选择封装、运行时查找、继承还是简单的扩展方法,目标都是一样的:减少条件式,将逻辑移到它该去的地方。

请记住

  • 条件式也不错。

  • 条件杂乱。

  • 简洁的代码不依赖于分散在各个类中的多个 if else 语句。

  • 评估上下文并进行相应的重构。

正如德里克所说,"这取决于你的语境"。但有一点是肯定的:产品并不总是单纯的产品--有时,它是一个重新思考设计的信号。

Earn More by Sharing What You Love

Do you create content for developers working with .NET, C#, Java, Python, or Node.js? Turn your expertise into extra income!

Let's Stay in Touch!

Join our newsletter, you’ll get exclusive access on article updates. We value your privacy

Key in blue circle

立即获取免费的 30 天试用版密钥

Your trial license will be sent to your email address

无任何限制。100% 解锁。无需信用卡。

bullet_checked无需信用卡或创建账户无任何限制。100% 解锁。无需信用卡。
  • Logo Aetna
  • Logo NASA
  • Logo GE
  • Logo Porsche
  • Logo USDA
  • Logo Qatar
Join Millions of Engineers who’ve tried IronPDF
获取您的无义务咨询
填写下面的表格或通过sales@ironsoftware.com
您的资料将始终保密。
深受全球数百万工程师信赖
Iron Software 的客户徽标
立即获取您的免费30 天试用密钥
无需信用卡或创建账户