【问题标题】:How do you deal with new features of C# so that they don't lead to poorly written code?您如何处理 C# 的新特性,以免它们导致编写糟糕的代码?
【发布时间】:2009-03-30 12:01:50
【问题描述】:

C# 3.0 中引入了许多让我感到不安的特性,例如对象初始化器、扩展方法和隐式类型变量。现在在 C# 4.0 中,我越来越担心动态关键字之类的东西。

我知道这些功能中的每一个都可以以适当的方式使用但是在我看来,它们使开发人员更容易做出错误的编码决定,从而编写更糟糕的代码.在我看来,微软正试图通过使编码变得简单和不苛刻来赢得市场份额。就我个人而言,我更喜欢一种严谨的语言,它对我的​​编码标准提出了更高的要求,并迫使我以 OOP 方式构建事物。

以下是我对上述功能的担忧的几个示例:

对象构造函数可以执行不暴露给消费者的重要逻辑。这是在对象开发者的控制之下。对象初始化器取消了这种控制,并允许使用者决定初始化哪些字段。

编辑:我没有意识到你可以混合构造函数和初始化程序(我的错),但这在我看来开始变得混乱,所以我仍然不相信这是向前迈出的一步。

允许开发人员使用扩展方法扩展内置类型允许所有人开始将他们最喜欢的宠物方法添加到字符串类中,这可能会导致令人眼花缭乱的选项数组,或者需要对编码标准进行更多监管才能除草这些都出来了。

允许隐式类型变量允许快速而肮脏的编程,而不是正确的 OOP 方法,这可能很快成为整个应用程序中难以管理的变量。

我的担心有道理吗?

【问题讨论】:

  • RobW :您应该重新表述您的问题。 “微软是对的吗”是有争议的,而“你如何处理 c# 的新特性才不会导致代码写得不好”不是
  • 好的,试试吧!不是想争论,这就是为什么我举了我的观点的例子,我对其他开发人员的想法很感兴趣。
  • 这也是一个“讨论”问题,没有明确的答案(只有意见),因此社区 wiki 是合适的。
  • 如果是这种情况,我会投票重新开放。
  • @RobW - 我更喜欢严谨、纪律严明且具有更高标准的开发人员,而不是强制执行此类行为的语言。您描述的开发人员会找到编写糟糕代码的方法;该死的语言。

标签: c# coding-style


【解决方案1】:

对象初始化器仅允许客户端在构造后立即设置属性,不会放弃控制,因为调用者仍必须确保满足所有构造函数参数。

我个人觉得他们添加的很少:

Person p1 = new Person("Fred");
p1.Age = 30;
p1.Height = 123;

Person p2 = new Person("Fred")
{
    Age = 30;
    Height = 123;
};

我知道很多人不喜欢“var”关键字。我可以理解为什么这是一种公开的滥用行为,但我不介意它的类型非常明显:

var p1 = new Person("Fred");
Person p2 = GetPerson();

在上面的第二行中,类型并不明显,尽管有方法名称。在这种情况下,我会使用该类型。

扩展方法——我会非常谨慎地使用,但它们对于使用便捷方法扩展 .NET 类型非常有用,尤其是 IEnumerable、ICollection 和 String。 String.IsNullOrEmpty() 作为扩展方法非常好,因为它可以在空引用上调用。

我认为您不必担心,优秀的开发人员总是会尊重地使用他们的工具,而糟糕的开发人员总是会想方设法滥用他们的工具:限制工具集并不能解决这个问题。

【讨论】:

  • 感谢构造函数初始化组合的指针,问题基于此更新。
  • 没有问题。我相信对象初始化器是为匿名类型添加的,因为该类型没有名称,所以无法指定构造函数!我知道为什么 C++ 之类的语言仍然坚持名称 == 到类名的 cstr:一个名为 Initialize() 的初始化方法,如 Ruby,在 IMO 上会更好。
  • 实际上,您对对象初始化程序是完全错误的。有一个很大的区别:在您的第一个“旧”样式示例中,每个分配都将被视为原子操作,可能会导致对象状态不一致的时间窗口。 “新”语法将一起评估
  • 我查看了反射器。在 OI 情况 (p1) 中,实例在 init 期间被分配给一个临时 var,然后才被放入 p1。所以,是的,你是正确的,使用 OI 会延迟分配直到 init 完成。不过,它似乎无法在多线程环境中提供保护。
  • 对 String.IsNullOrEmpty() 很好,我假设字符串 s = null; s.IsNullOrEmpty();会扔。很高兴知道。 +1
【解决方案2】:

您可以通过将限制写入编码标准来限制开发人员可以使用的 C# 3.0 功能。然后,在签入前审查代码时,应发现任何违反这些规则的代码并拒绝签入。一种这样的情况很可能是扩展方法。

显然,您的开发人员会想要使用新功能 - 所有开发人员都这样做。但是,如果你有很好的、有据可查的理由说明为什么不应该使用它们,那么优秀的开发人员会遵循它们。随着新信息的曝光,您还应该对修改这些规则持开放态度。

使用 VS 2008,您可以指定要定位的 .NET 版本(右键单击解决方案并选择属性 > 应用程序)。如果您将自己限制在 .NET 2.0 中,那么您将无法获得 .NET 3.5 中的任何新功能。如果您想使用某些功能,显然这无济于事。

但是,我认为您对vars 的担心是没有根据的。 C# 仍然像以往一样是强类型的。声明为var 只是告诉编译器为该变量选择最佳类型。该变量不能更改类型,它始终是int 或Person 或其他任何类型。就我个人而言,我遵循与 Paul Ruane 相同的规则;如果从语法中明确类型,则使用var;如果没有明确命名类型。

【讨论】:

  • 我不会有兴趣为一家对新功能引入禁忌的公司工作,因为这相当于使用旧技术,您不会扩展您的技能和经验。
  • 虽然我原则上对此表示同情,但在商业世界中,我不会说 C# 2.0(例如)完全是一种“旧技术”。如果他们用 COBOL 编写新软件,我可能会同意。
  • @SO Troll - 我要指出的是,您可以限制开发人员可以做的事情。例如,您可能无法在服务器上安装 .NET 3.5。
  • 我会在他们让我使用其他可用工具的受限子集的那一天提交通知。我得到报酬(在许多其他事情中)来决定哪种语言结构非常适合给定的情况。你不能像那样对程序员进行微观管理,因为他们会不高兴并且会离开。
【解决方案3】:

我看到你的立场是这样表达的:

构建一个开发环境, 任何傻瓜都可以使用,你得到的是 许多傻瓜在发展。

这是非常正确的,但相比之下我们其他人看起来不错。我认为这是一件好事。我见过的最有趣的帖子之一说

不应低估VB。它是一个非常强大的工具 让白痴远离这个 [C++] 新闻组。

更严重的是,工具是否危险取决于使用者的智慧。防止愚蠢的唯一方法是防止行动。 foreach 看起来无害,但您甚至无法在迭代集合时删除项目,因为删除项目会使迭代器无效。你最终会抛弃它们,转而使用经典的 for 循环。

【讨论】:

    【解决方案4】:

    我认为你们中唯一真正合理的问题是过度使用扩展方法。当重要功能只能通过扩展方法访问时,有时组中的每个人都很难发现和使用该功能。

    担心对象初始化器和“var”关键字似乎很挑剔。两者都是简单且可预测的语法,可用于使代码更具可读性,我不清楚您如何看待它们被“滥用”。

    我建议您通过达成一致的书面编码标准来解决此类问题。如果没有人能想出充分的理由来使用新的语言特性,那么毕竟没有必要使用它们。

    【讨论】:

      【解决方案5】:

      对象初始化器只是花哨的语法。开发人员可以用它们做任何他以前不能做的事情 - 但是它们确实为您节省了几行代码。

      如果“扩展内置类型”是指扩展方法 - 同样,这并不是什么新鲜事,只是更好的语法。这些方法是静态方法,出现就好像它们是成员一样。内置类保持不变。

      Linq 需要隐式类型变量。我还将它们与具有大量类型参数的泛型一起使用。但我同意我不希望看到它们被专门使用。

      当然,每个功能都可能被滥用,但我认为这些新功能实际上让您编写的代码更易于阅读。

      【讨论】:

        【解决方案6】:

        关于 var 的一个重要缓解因素是它永远不能在作用域之间移动。它不能是返回类型或参数类型。这让我觉得它更安全,因为它始终是紧密类型的,并且始终是一种方法的实现细节。

        【讨论】:

        • 你在考虑匿名类型,var 只是隐式类型。
        • "在方法范围内声明的变量可以具有隐式类型 var" msdn.microsoft.com/en-us/library/bb383973.aspx 。 var 只能是方法局部变量,不能是类级成员或返回类型或参数类型。
        【解决方案7】:

        之所以引入新功能,是因为 Microsoft 意识到它们对于实现新语言功能是绝对必要的。例如,像 LINQ。所以你可以使用相同的策略: 1)了解这些功能, 2) 在您发现对您绝对必要之前不要使用。

        如果您真的了解这些功能,我敢打赌您很快就会觉得有必要。 :)

        【讨论】:

        • 我完全意识到 C# 3 中的许多新东西都是由 LINQ 驱动的,正如我所说,我知道每个功能都有其适当的用途,我的观点是,将所有这些更改加在一起具有对语言的负面影响。
        • 恕我直言,如果您查看用任何语言编写的程序的数量,您会发现各种不同类型的滥用。 :) 当然,有些语言更容易被误用。像 Perl。我是一个架构极客,所以我认为每个开发人员都应该首先考虑这一点。
        【解决方案8】:

        至少对于“var”和初始化器,你并不能真正做任何新的事情,它只是一种新的编写方式。虽然看起来对象初始值设定项编译为稍微不同的 IL。

        关于扩展方法的一个真正让我大吃一惊的角度是,您可以将它们放在接口上。这意味着一个类可以通过实现一个接口来继承具体的代码。而且由于一个类可以实现多个接口,这意味着,以一种迂回的方式,C# 现在有类似多重继承的东西。所以这是一个绝对应该小心处理的新功能。

        【讨论】:

          【解决方案9】:

          我的担心有道理吗?

          没有。这是对简单问题的简单回答的另一个版本。

          【讨论】:

          • 如果你愿意,请投票给我,我知道这是一个轻率的答案。但问题是他的担忧是否有充分的理由支持,在我看来,不,他们没有。我的意思是,为什么要忽略经典的“属性只是语法糖 == 糟糕的代码”抱怨?
          猜你喜欢
          • 1970-01-01
          • 2022-01-20
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2011-05-04
          • 1970-01-01
          • 2021-04-05
          • 1970-01-01
          相关资源
          最近更新 更多