#region是反模式或代码气味吗?


264

C#允许使用#region/ #endregion关键字使代码区域在编辑器中可折叠。每当我这样做时,我都会隐藏可能会重构为其他类或方法的大量代码。例如,我见过一些方法,其中包含500行代码以及3或4个区域,只是为了使其易于管理。

那么明智地使用区域是否会带来麻烦呢?对我来说似乎是这样。


9
仅供参考:CodeMap几乎消除了对区域的需求。visualstudiogallery.msdn.microsoft.com/…-单击,然后您进入方法/属性/其他。我每天都在使用它,这真是令人惊讶,您从生产力和认知方面也获得了多少收益。您将获得该课程更清晰的“鸟瞰图”。

7
任何人都可以将此作为Wiki吗?这个问题没有正确或错误的答案(在合理范围内),这几乎是完全主观的。
Ed S.

6
杰夫·阿特伍德(Jeff Atwood)讨厌他们,因为他们值得。他辩称他们隐藏了错误的代码。
布赖恩

3
代码气味是不淋浴也不使用除臭剂的开发人员!
marko

5
Febreeze在硬皮沙发上挤了几下,用臭代码精心制作了Regions。它使您可以忍受,直到找到(时间)金钱来替换它为止。
Newtopian 2013年

Answers:


284

代码异味是一种症状,表明设计中存在一个问题,这可能会增加错误的数量:对于区域而言,情况并非如此,但是区域可能会导致产生代码异味,就像长方法一样。

以来:

反模式(或反模式)是在社交或企业运营或软件工程中使用的模式,通常可以使用,但实际上无效和/或适得其反

区域反模式。他们需要做更多的工作,这些工作不会提高代码的质量或可读性,也不会减少错误的数量,并且可能只会使代码更难以重构。

不要在方法内部使用区域;重构

方法必须简短。如果方法中只有十行,则在处理其他五行时,可能不会使用区域来隐藏其中的五行。

同样,每种方法都只能做一件事情。另一方面,区域旨在分离不同的事物。如果您的方法执行A,然后执行B,则创建两个区域是合乎逻辑的,但这是错误的方法。相反,您应该将方法重构为两个单独的方法。

在这种情况下使用区域也会使重构更加困难。假设您有:

private void DoSomething()
{
    var data = LoadData();
    #region Work with database
    var verification = VerifySomething();
    if (!verification)
    {
        throw new DataCorruptedException();
    }

    Do(data);
    DoSomethingElse(data);
    #endregion

    #region Audit
    var auditEngine = InitializeAuditEngine();
    auditEngine.Submit(data);
    #endregion
}

使第一个区域崩溃而将注意力集中在第二个区域上不仅有风险:我们可以轻松地忘记阻止流程停止流动的异常(可能有一个带有a的保护子句return,这更加难以发现),而且还会有一个问题如果代码应该以这种方式重构:

private void DoSomething()
{
    var data = LoadData();
    #region Work with database
    var verification = VerifySomething();
    var info = DoSomethingElse(data);

    if (verification)
    {
        Do(data);
    }

    #endregion

    #region Audit
    var auditEngine = InitializeAuditEngine(info);
    auditEngine.Submit(
        verification ? new AcceptedDataAudit(data) : new CorruptedDataAudit(data));
    #endregion
}

现在,区域没有意义,如果不查看第一个区域中的代码,就不可能阅读和理解第二个区域中的代码。

我有时看到的另一种情况是:

public void DoSomething(string a, int b)
{
    #region Validation of arguments
    if (a == null)
    {
        throw new ArgumentNullException("a");
    }

    if (b <= 0)
    {
        throw new ArgumentOutOfScopeException("b", ...);
    }
    #endregion

    #region Do real work
    ...
    #endregion
}

当参数验证开始跨越数十个LOC时,很容易使用区域,但是有一种更好的方法来解决此问题:.NET Framework源代码使用的一种方法:

public void DoSomething(string a, int b)
{
    if (a == null)
    {
        throw new ArgumentNullException("a");
    }

    if (b <= 0)
    {
        throw new ArgumentOutOfScopeException("b", ...);
    }

    InternalDoSomething(a, b);
}

private void InternalDoSomething(string a, int b)
{
    ...
}

不要使用方法以外的区域进行分组

  • 有人用它们将字段,属性等组合在一起。这种方法是错误的:如果您的代码符合StyleCop,则字段,属性,私有方法,构造函数等都已经组合在一起并且很容易找到。如果不是,那么该是时候开始考虑应用确保整个代码库统一的规则了。

  • 其他人则使用区域来隐藏许多相似的实体。例如,当您有一个包含一百个字段的类(如果计算注释和空格,则至少要编写500行代码),您可能会想将这些字段放在一个区域内,将其折叠并忘记它们。再一次,您做错了:在一个类中有这么多字段,您应该更好地考虑使用继承或将对象切成几个对象。

  • 最后,有些人倾向于使用区域将相关的事物组合在一起:事件及其委托,或者与IO相关的方法与与IO相关的其他方法,等等。在第一种情况下,它变得一团糟,难以维护,阅读并理解。在第二种情况下,更好的设计可能是创建多个类。

区域有很好的用途吗?

否。有一个旧用途:生成的代码。尽管如此,代码生成工具只需要使用部分类即可。如果C#具有区域支持,则主要是因为这种传统用途,并且由于现在有太多人在其代码中使用区域,因此在不破坏现有代码库的情况下就不可能删除它们。

考虑一下goto。语言或IDE支持功能这一事实并不意味着应每天使用该功能。StyleCop SA1124规则很明确:您不应使用区域。决不。

例子

我目前正在对同事的代码进行代码审查。该代码库包含许多区域,并且实际上是如何不使用区域以及区域为何导致不良代码的完美示例。这里有些例子:

4000 LOC怪物:

我最近在Programmers.SE上的某个地方读到,当文件包含太多usings(在执行“删除未使用的用法”命令之后)时,这是一个好兆头,表明该文件中的类做得太多。这同样适用于文件本身的大小。

在查看代码时,我遇到了一个4000 LOC文件。看起来,这段代码的作者只是简单地将同一行的15行方法复制粘贴了数百次,只是略微更改了变量的名称和被调用的方法。一个简单的正则表达式允许通过添加一些泛型将文件从4000 LOC减少到500 LOC。我非常确定,通过更巧妙的重构,此类可以减少到几十行。

通过使用区域,作者鼓励自己忽略该代码无法维护且编写不良的事实,并大量复制代码而不是对其进行重构。

地区“ Do A”,地区“ Do B”:

另一个很好的例子是怪物初始化方法,该方法仅执行任务1,然后执行任务2,然后执行任务3,等等。有五个或六个完全独立的任务,每个任务都在容器类中进行初始化。所有这些任务都被分组为一种方法,并分组为区域。

这有一个优点:

  • 通过查看区域名称可以很清楚地理解该方法。话虽如此,重构后的相同方法将与原始方法一样清晰。

另一方面,问题是多方面的:

  • 区域之间是否存在依赖关系并不明显。希望不会重复使用变量。否则,维护工作可能更像一场噩梦。

  • 该方法几乎无法测试。您如何轻松地知道一次执行20件事的方法是否正确?

字段区域,属性区域,构造函数区域:

审阅的代码还包含许多区域,这些区域将所有字段,所有属性组合在一起,等等。这存在一个明显的问题:源代码增长。

当您打开文件并看到巨大的字段列表时,您更倾向于先重构该类,然后再使用代码。在区域中,您习惯于折叠东西而忘却它。

另一个问题是,如果您在所有地方都这样做,则会发现自己创建了一个块区域,这没有任何意义。我所检查的代码实际上就是这种情况,其中#region Constructor包含一个构造函数。

最后,字段,属性,构造函数等应该已经按顺序排列。如果它们是并且它们符合约定(以大写字母开头的常量等),则已经清楚元素类型在何处停止而其他在何处开始,因此您无需为此显式创建区域。


12
我认为#region至少有一些可辩护的用法-例如,折叠保护子句(检查输入参数),如果不折叠,则会损害方法的要旨或“实质”。另一个例子是API边界上的异常处理。您通常不想通过调用其他方法来包装异常来影响堆栈跟踪,因此您需要包装和重新抛出几行代码。这通常也是不相关的代码,可以安全地折叠起来。
Daniel B

9
现实检查。我已经看到很多方法间的#region很有帮助。当您有了带有嵌套控制逻辑的数百行方法时,其中有数十到数百行带有其中的一些-谢天谢地,白痴至少将它放在了区域中。
2013年

37
@radarbob:简而言之,区域有助于编写糟糕的代码,而这些代码本来不应该存在。
阿森尼·穆尔琴科

40
-1(如果我有声誉)。即使您的类型成员井井有条且相互独立,也可能有很多成员。区域使您不必滚动到10或12个属性以及相关的getter和setter即可滚动到要使用的方法。唯一的选择是单独折叠所有属性,这不是我喜欢的。提供的大规模显示/隐藏功能区域非常有用。我同意方法内区域。
Asad Saeeduddin

13
我完全不同意这个答案:代码臭味和区域彼此无关。如果您的代码发臭,无论有无区域,它都会发臭。我使用区域的方式是将我的班级分成区域。通常,我仍然坚持相同的模式:公共属性,公共方法,私有字段,私有方法。那是我将拥有区域的唯一用途。除此之外,您可能在代码中破坏了SRP主体。
Alexus 2015年

112

令我感到不可思议的是,有多少人如此讨厌地区!

我完全同意他们的许多反对意见:将代码#region隐藏到a中以使其看不见是一件坏事。将一个类划分为何#regions时应该将其重构为单独的类显然是错误的。使用#region嵌入冗余语义信息是多余的。

但是,这些都不意味着在代码中使用区域存在任何内在的错误!我只能假设大多数人的反对意见来自在其他人倾向于不正确使用IDE功能的团队中工作。我拥有独自工作的能力,并且我对地区帮助组织工作流程的方式表示赞赏。也许这是我的强迫症,但我不喜欢一次在屏幕上看到一堆代码,无论它写得多么整洁。将事物分离成逻辑区域可以使我折叠关心的代码来处理我所做的代码关心。我并不是在忽略写得不好的代码,对其进行重构的意义不大,而且附加的“元”组织是描述性的,而不是毫无意义的。

现在,我已经花了更多时间在C ++中工作,更直接地使用Windows API进行编程,我发现自己希望对区域的支持与对C#的支持一样好。您可能会争辩说,使用备用GUI库会使我的代码更简单或更清晰,从而消除了将无关的代码噪声从屏幕上移开的需要,但是我还有其他不想这样做的原因。我对自己的键盘和IDE足够精通,可以使扩展/折叠细分为区域的代码花费的时间不到一秒钟。我节省了精力,试图将自己的注意力集中到我目前正在处理的代码上,这是值得的。它们全都属于一个类/文件,但并非同时都属于我的屏幕。

关键是要使用#regions代码来分离和逻辑划分代码不是一件坏事,要不惜一切代价避免。正如Ed所指出的,这不是“代码异味”。如果您的代码有味道,则可以确保它不是来自区域,而是来自您尝试将其埋在这些区域中的任何代码。如果某个功能可以帮助您更井井有条,或者编写更好的代码,那么我就说使用它。如果它成为障碍,或者您发现自己使用不正确,请停止使用它。如果情况变得更糟,而您又不得不与使用它的人一起工作,请记住键盘快捷键以关闭代码概述:Ctrl+ MCtrl+P。别再抱怨了 有时候,我觉得这是另一种方式,那些希望被视为“真实”,“核心”程序员的人喜欢尝试证明自己。避开区域比避开语法着色更好。它并没有使您成为更强壮的开发人员。

所有这样说的,区域的方法都只是纯属无稽之谈。每当您发现自己想要这样做时,都应该将其重构为单独的方法。没有理由。


9
说得好。使用区域进行组织仅比切换IDE的“视图空白”选项有害。这是个人喜好。
乔什(Josh)

24
我使用带有10或20个属性的ViewModels在WPF上工作,这些属性仅将属性包装在我的模型上,我喜欢区域-我可以将那些属性藏在一个区域中(它们永远都不需要被触摸),并一直关注相关代码。
柯克·布罗德赫斯特

4
完全同意。在.NET 2.0中,属性的长度约为8-10行。当一个类中有20多个属性时,它们会占用大量空间。区域非常适合折叠它们。
克里斯托夫·克莱斯

6
@Kristof:.NET 4.0中的属性也可以进行简单的输入验证。就我的目的而言,自动属性并不是那么神奇。
科迪·格雷

8
我愿意向左打赌,那些讨厌地区的人要么从未开发过WPF应用程序,要么从未真正使用过WPF的定义功能,例如数据绑定和命令绑定。仅仅设置您的代码以使这些工作占用大量空间,并且您通常不必再次查看它们。
l46kok 2012年

69

首先,我再也受不了“代码气味”这个词了。它使用得太频繁了,并且大部分时间都被无法识别优质代码的人扔掉。无论如何...

我个人不喜欢使用很多地区。这使获取代码变得更加困难,而代码正是我感兴趣的代码。当我有很多不需要经常接触的代码时,我喜欢使用区域。除此之外,它们似乎妨碍了我,“私有方法”,“公共方法”等区域使我发疯。它们类似于各种评论i++ //increment i

我还要补充一点,区域的使用实际上不能成为“反模式”,因为该术语通常用于描述程序逻辑/设计模式,而不是文本编辑器的布局。这是主观的;使用对您有用的东西。由于您对区域的过度使用,您永远都不会以无法维护的程序告终,这就是反模式的全部意义所在。:)


2
通常,我会为您的代码气味注释而投票,但是在这种情况下,它是准确的。非代码不能成为代码的味道。+2!

7
哈哈,嗯,我不是说“代码气味”一词不能正确使用。可以,但是我看到这些天来了那么多,以至于我的立即反应只是烦恼,尤其是当它来自确实只是在重复他们听到的声音而又不理解它或不认真思考的人。诸如“函数中的5个以上局部变量是代码味道”之类的语句仅说明该人实际上没有多少经验。
Ed S.

13
不确定我是否理解您对代码气味的评论。代码气味并不表示存在问题,只是可能存在问题。
Craig

7
+1代表术语代码气味。当我看到一则声称私有方法是代码气味的帖子时,我受够了。但是总的来说,我不同意你对地区的厌恶。我很容易分心。实际上,如果VS具有VB4模式(您一次只能显示一个方法),我将非常喜欢。
乔什(Josh)

7
只是想插话并说滥用一个完美的隐喻不应贬低这个隐喻。“代码气味”是一个很好的隐喻,可以立即理解,记住和使用。在很多地方,应用“代码气味”隐喻仍然是传达观点的最佳方法。
埃里克·金

23

是的,区域有代码气味!

我很高兴看到将区域从编译器中完全删除。每个开发人员都会想出自己的毫无意义的修饰方案,这种方案永远不会对其他程序员有价值。我与想要装饰和美化他们的婴儿的程序员有一切关系,与任何真正的价值无关。

您能想到一个示例,尽管您“哎呀,我希望我的同事在这里使用过某些区域!”?

即使我可以将IDE配置为自动扩展所有区域,但它们仍然令人感到烦恼,并且有损于阅读真实的代码。

如果我所有的公共方法都聚集在一起,我真的会在乎。恭喜,您知道变量声明和初始化之间的区别,无需在代码中显示它!

毫无价值的修饰!

另外,如果您的文件需求和使用区域的“信息体系结构”,您可能想解决核心问题:您的课程太大了!将其分解成更小的部分会更加有益,并且在正确完成后可以增加真正的语义/可读性。


#regions是编译器的一部分吗?我以为它们只是对IDE的指令,可以忽略。
史蒂夫·鲁库兹

2
编译C#代码时,编译器将需要忽略它们。如果不忽略它们,它将对它们产生影响。我是那样说的。
2012年

1
“您能想到一个例子,您虽然说“老兄,我希望我的同事在这里使用过一些区域!”?” 是的,非常非常。当我有一个包含私有方法和公共方法的类时,我会在区域中将它们分解,因为重构公共方法时,您不必触摸私有代码,反之亦然。
Anshul 2015年

您显然从未见过外包代码。因此,很多时候在外包代码中看到区域会很棒。即使代码很烂,但如果从某种逻辑上讲将它们组合在一起,那么至少至少会更容易理解。虽然,如果他们的代码不是合乎逻辑的机会,那么区域也不会是这样,那么可能会使情况变得更糟。如果正确使用,区域会很棒。
Nickmccomb

15

我个人使用区域作为将各种类型的方法或部分代码组合在一起的一种方式。

因此,打开后的代码文件可能如下所示:

  • 公共财产
  • 建设者
  • 保存方法
  • 编辑方法
  • 私人帮手方法

我没有将区域放在方法内部。恕我直言,这是代码气味的迹象。我曾经遇到过一种方法,该方法长1200行以上,其中有5个不同的区域。真是恐怖的景象!

如果您将其用作组织代码的方式,从而可以更快地为其他开发人员查找内容,那么我认为这并不意味着麻烦。如果您使用它来隐藏方法内部的代码行,我想是时候重新考虑该方法了。


14
啊。我知道这是一个主观的话题,但是,我真的受不了这个计划。以我的经验,添加的“组织”根本无济于事,只是让浏览代码变得头疼。我也更喜欢不仅按访问修饰符而且按逻辑责任对方法进行分组。对于公共接口,我通常将每个方法/属性分组在一起,但通常受保护的方法可能会调用私有帮助器函数,在这种情况下,我更喜欢帮助器函数(只能在其中使用)在其上方或下方。调用它的方法。
Ed S.

3
@Ed S.-这就是为什么我说“可能看起来像”。这是非常主观的。我并不是说每个文件都应该像这样。如果他们这样做,我会感到惊讶。只是有关复杂主题的示例。:)
Tyanna 2011年

哦,我知道,就像我说的那样;这是主观的。对您/您的团队有用的任何东西。我只是为这个方案准备了它,因为它对我不起作用,但是我必须维护一个做到这一点的项目。这让我发疯。
Ed S.

3
@EdS。因此,请进入vs中的选项并关闭区域。问题解决了。
安迪

为什么您的对象具有保存方法?:(
TheCatWhisperer

10

使用#region块使非常大的类可读性通常是违反单一责任原则的标志。如果他们习惯于对行为进行分组,那么该类也可能做得太多(再次违反SRP)。

坚持“代码气味”的思路,#region代码块本身并不是代码气味,但它们更像是“代码狂潮”,因为它们试图隐藏气味。虽然我过去曾经大量使用它们,但是当您开始进行重构时,您会发现它们很少,因为它们最终没有隐藏太多。


5

这里的关键词是“明智的”。很难想象将区域放入方法内部是明智的情况。这很可能是代码隐藏和懒惰。但是,有充分的理由在自己的代码中到处都有一些区域。

如果有很多区域,我确实认为这是一种代码味道。区域通常暗示将来可能进行重构。很多地区意味着实际上没有人接受过提示。

明智地使用它们可以在具有多个方法的单个类的结构与每个仅包含几个方法的多个类的结构之间提供良好的中间立场。当一个类开始将其重构为多个类但还远远不够时,它们最有用。通过将相关方法分组在一起,如果以后数量继续增加,我以后可以轻松地将一组相关方法提取到自己的类中。例如,如果我有一个接近500行代码的类,那么在一个区域中使用总共200行代码收集在一起的一组方法可能是重构的好方法-而在另一个区域中有100行代码方法也可能是一个很好的目标。

我喜欢使用区域的另一种方法是减少重构大型方法的负面影响之一:许多小型,简洁,易于重用的方法,读者必须滚动浏览才能找到另一种几乎不相关的方法。区域可能是一种为读者提供元封装方法及其帮助程序的好方法,因此,使用类的其他方面的人员可以将它们折叠起来并迅速消除该部分代码。当然,这仅在您的区域组织得很好并且实际上被用作记录代码的另一种方式时才有效。

通常,与不使用区域相比,我发现区域可以帮助我保持井井有条,帮助“编写文档”我的代码,并帮助我更快地找到要重构的地方。


4

我主要使用CRUD服务器类的区域来组织各种类型的操作。即使那样,我也可以很高兴地没有他们。

如果广泛使用,它将引起危险信号。我将寻找责任过多的课程。

以我的经验,一个有数百行代码的方法绝对是一种味道。


4

我的经验法则是:如果文件中有5个以上的区域,那是代码的味道

即,描述字段,方法,属性和构造函数可能很好,但是如果您开始将其他所有方法包装在它自己的区域中,则表示严重错误

..是的,我经常参与许多项目,通常是因为编码标准不佳,代码生成或两者兼而有之。必须快速切换Visual Studio中的所有轮廓才能获得良好的代码概述,这很快就过去了。


4

区域已使用

在Windows窗体应用程序之前,我曾亲自使用它们进行“手动编码”界面事件。

但是,在我的工作中,我们使用代码生成器来处理SQL,并且它自动使用区域来整理其选择,更新,删除等类型的方法。

因此,尽管我不经常使用它们,但它们对于删除大块代码非常合适。


1
我使用过类似的代码生成器,并且更喜欢使用局部类来删除生成的代码。
Craig

我们这样做,区域位于生成的代码内,以使其更易于阅读或调试(如果需要)。

4

如果您代码中包含区域,那么您肯定会遇到问题(除非生成代码)。将区域放入代码中基本上是在说“重构”。

但是,还有其他情况。我回想了一段时间:一个有几千个预先计算的项目的表。这是对几何的描述,没有表格中的错误,永远不会有机会查看它。当然,我可以从资源或类似资源中获取数据,但是这将排除使用编译器来帮助使其易于阅读的情况。


1
对于存储在单独文件中的部分类,或者使用HardcodedDataSource实现注入的IMyDataSource,这是一个更好的用例。
Bryan Boettcher

3

在最近的项目中,有一种1700行方法,其中嵌入了多个区域。有趣的是,这些区域划分了在该方法中正在执行的不同操作。我能够在每个区域上执行重构->提取方法,而不会影响代码的功能。

通常,用于隐藏样板代码的区域很有用。我建议不要使用区域来隐藏属性,字段等,因为如果它们在类中工作时太笨拙而无法查看,则可能表明该类应该进一步细分。但是,作为一个硬规则,如果要将区域放入方法中,则最好提取另一种方法来解释正在发生的事情,而不是将该块包装在区域中。


3

可以在质量好的代码中使用区域吗?大概。我敢打赌,在许多情况下,它们都是如此。但是,我的个人经历使我非常怀疑-我看到几乎完全被滥用的区域。我会说我很疲倦,但仍然很乐观。

我可以将迄今为止使用的区域代码大致分为三类:

  • 分解系数差的代码:我见过的大多数代码都将区域用作穷人分解系数的工具。例如,一类已经发展到可以针对不同目的对其进行专门化处理的地步,可以改为将其分为不同的区域,每个目的一个区域。

  • 针对问题域使用错误的库(有时甚至是错误的语言)编写的代码通常,当程序员针对问题域使用的库集不正确时,您会发现代码变得非常冗长-带有许多辅助功能确实不属于它们(它们可能属于自己的库)。

  • 学生或应届毕业生编写的代码。某些程序和课程似乎试图通过各种奇怪目的将区域灌输给学生。您会看到区域将源代码乱七八糟,直到区域标签与代码行的比率在1:5或更差的范围内。


3

我会说这是“代码气味”。

反模式通常是软件中的基本结构性问题,而区域本身只会在编辑器中造成令人讨厌的行为。使用区域实际上并没有本质上的坏处,但是经常使用它们,尤其是隐藏代码块可以表明在其他地方还存在其他独立的较大问题。


@安德鲁·格林(Andrew Grimm):是的
whatsisname 2011年

3

我仅将区域用于一件事(至少我无法想到使用它们的其他地方):将单元测试分组为一种方法。

我通常每个类都有一个测试类,然后通过使用具有方法名称的区域将每个方法的单元测试分组。不知道那是代码的味道还是什么,但是由于基本思想是单元测试不需要更改,除非它们因为代码中的某些内容发生更改而中断,这使我更容易找到特定方法的所有测试很快。

我过去可能曾经使用区域来组织代码,但是我不记得上一次这样做了。不过,我坚持在单元测试课程中学习所在的地区。


1
您是否曾经测试过多种方法?
玛西(Marcie)

我不太了解这个问题或您的目标是什么。答案是:不,单元测试始终仅针对一种方法,或者仅针对一种方法的某个方面。
Anne Schuessler

2

我相信这是一种反模式,并且坦率地认为应该将其消除。但是,如果您处于在标准位置工作的不幸境地,Visual Studio会提供一个很棒的工具来最小化您每次看到一个区域时想要呕吐的数量。I Hate #Regions

这个插件将使该区域的字体大小很小。它们也会被扩展,因此您不必点击ctr + m + l即可打开所有区域。它不能解决这种形式的代码癌症,但是确实可以忍受。


0

我使用区域来包含可见性和成员类型的每种组合。因此,所有私有功能都进入一个区域,等等。

我这样做的原因不是,所以我可以折叠代码。这是因为我编写了编辑器脚本,因此可以插入对代理的引用:

#region "private_static_members"
 /// <summary>
 /// cache for LauncherProxy
 /// </summary>
private static LauncherProxy _launcherProxy;
#endregion

#region "protected_const_properties"
protected LauncherProxy LauncherProxy{
  get{
    if(_launcherProxy==null) {
      if (!God.Iam.HasProxy(LauncherProxy.NAME)) {
        God.Iam.RegisterProxy(new LauncherProxy());
      }
      _launcherProxy=God.Iam.Proxy(LauncherProxy.NAME) as LauncherProxy;
    }
    return _launcherProxy;
  }
}
#endregion

放入代码中,并将每个部分整齐地塞入适当的区域。

在这种情况下,宏将分析我的项目,给我一个代理列表框,并为我想要的代码注入代码。我的光标甚至都没有动。

在学习C#的开始,我曾考虑过使用区域来保持共同性,但这是一个命中注定的命题,因为它并非始终都是一对一的关系。谁想为两个地区使用的成员感到烦恼,或者甚至开始按照这些条款分手。

分离的唯一另一种类型是方法-我将把方法分解为Commands,Functions和Handlers,所以我将有一个公共,私有等Commands等的区域。

这给了我粒度,但是我可以依靠的是一致的,明确的粒度。


当我获得125分的低票时,-1。您正在添加不需要的代码行。为什么为什么为什么要在属性周围放置一个区域... if(God.Iam.AbusingRegions()== true)myName =“ Mark”
DeadlyChambers 2014年

1
@DeadlyChambers原因在第二段中说明-我正在使用编辑器宏将常见的代码模式注入文件,这些区域有助于保持文件的结构,以便对相似的项进行分组。我不是在单个属性周围放置区域,而是所有属性都取决于其属性“ protected_const_properties”落入指定区域。您看过帖子吗?
2014年

1
您可能可以将其重构为:受保护的LauncherProxy LauncherProxy => God.Iam.GetOrAddProxy <LauncherProxy>(ref _launcherProxy); 因此,您现在不需要区域了。_launcherProxy也可以重命名为_launcherProxyCache,因此您不需要区域或在其中注释。
aeroson

0

区域是预处理器表达式-换句话说,它们被视为注释,基本上被编译器忽略。它们纯粹是Visual Studio中使用的可视工具。因此,#region并不是真正的代码味道,因为它不是代码。代码气味更确切地说是800行方法,其中嵌入了许多不同的职责。因此,如果您在一种方法中看到10个区域,则可能是用来隐藏代码气味。话虽如此,我已经看到它们非常有效地用于使一堂课更加悦目,更易于导航-也是在编写得井井有条的结构化课中!


0

区域是一个很漂亮的组织构想,但是没有考虑到某些开发人员倾向于对所有内容进行过度分类的趋势,按照大多数现代的OOP惯例,区域通常是不必要的...在某种意义上,它们是“气​​味”,使用它们通常表示您的类/方法太大,应该进行重构,因为您可能违反了SOLID原则的“ S” ...但是,就像任何气味一样,它不一定表示某些情况会变坏。

区域在功能代码中而不是在面向对象的代码IMO中具有更多的用途,在IMO中,有很长的顺序数据功能可以分解,但是有些时候我亲自在c#中使用了它们,并且它们几乎总是专注于您不需要/不想看的代码。对我来说,这些通常是用于NPoco或其变体的代码库中的原始SQL字符串常量。除非您真正关心数据如何通过您的ORM填充POCO对象,否则这些都是毫无意义的……如果您确实关心,请扩大区域和BAM!超过150行的复杂SQL查询为您带来观赏乐趣。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.