Juval Lowy的C#编码标准问题

时间:2009-06-16 18:57:01

标签: c# coding-style

我很喜欢并强烈推荐Juval Lowy's - C# Coding Standard。 Juval明确地避免了每个指令的基本原理,以保持标准的严格(参见前言)。但是,有一些指令我发现自己对基本原理感到好奇。

Lowy的C#标准中以下指令的具体原理是什么?
希望这些答案很难(非主观)。

1.13避免使用完全限定的类型名称。请改用“使用”语句。
这是性能问题吗?有时我只需要一个完全限定名称的实例,并且使用添加似乎很重。

1.26在无参数匿名方法上使用空括号。仅当匿名方法可以在任何委托上使用时,省略括号。
实际上我只是被第二句话弄糊涂了。对示例的解释会有所帮助,谢谢。

2.19避免定义自定义异常类
最小化数量有哪些考虑因素? (如果你确定它们,他接下来会给出指导(在2.20中)。)

2.29避免使用三元条件运算符
读者难以消化或其他考虑因素?

2.31避免在布尔条件语句中进行函数调用。分配到局部变量并检查它们。
我不认为我这样做,但我很好奇......为什么不呢?

2.47避免与一个成员的接口。
因为它总是/通常更优先做什么?一种方法接口何时工作?

2.53首选使用显式界面实现
为什么?另外,Jon Skeet disagrees here

提前致谢! 罗伯特

8 个答案:

答案 0 :(得分:10)

2.29避免使用三元条件运算符我对三元运算符的“简单”使用没有任何问题,但建议不要以嵌套方式使用它:

// This is fine
x := (conditionA) ? true_resultA : false_resultA;

// This would probably be clearer using if-then-elseif
x := (conditionA) ? 
       ((conditionA1) ? true_resultA1 : (condition2) ? true_result2 : false_result2) :
       ((conditionA2) ? true_resultA2 : false_resultA2);

答案 1 :(得分:9)

显然,我不是Juval,但我可以捅这些

1.13避免使用完全限定的类型名称。请改用“使用”语句。

性能不能成为问题。我确定这个问题是可读性的。

1.26在无参数匿名方法上使用空括号。仅当匿名方法可以在任何委托上使用时,省略括号。

public delegate void Foo1();
public delegate void Foo2(int val);

public void Foo()
{
    Foo1 first = delegate { Console.WriteLine("Hello world"); };
    Foo2 second = delegate { Console.WriteLine("Hello world"); };
    Foo1 third = delegate() { Console.WriteLine("Hello world"); };
    Foo2 fourth = delegate() { Console.WriteLine("Hello world"); }; // does not compile
}

如果没有parens,匿名委托可以应用于任何委托。对于parens,你是具体的代表签名。除非你真的需要灵活性,否则首选第二种语法。

2.19避免定义自定义异常类

同样,可读性是这里的问题。框架异常类很丰富且易于理解。更换它们时要小心。

2.29避免使用三元条件运算符

这是一个可读性和可扩展性的东西。我真的不同意,但这是一场标准的宗教斗争。

2.31避免在布尔条件语句中进行函数调用。分配到局部变量并检查它们。

部分是可读性,部分是为了便于调试。我已经开始将几乎所有内容都分配给临时变量,以便稍后在调试器中很容易找到它们。

2.47避免与一个成员的接口。

“避免”有点像“喜欢”,他只是在你做之前先说三思。如果您只有一个成员,那么界面是否真的在您的设计中建模有用且完整的东西?有一个只有一个成员的课程是非常罕见的,请认真考虑为什么你的界面有所不同。

2.53更喜欢使用显式接口实现

这类似于使用最少公共访问器的想法。如果您的班级不需要将界面设为公开,那么它可能不应该。显然,根据您的设计,这将显着不同,但鉴于大多数人只是在没有真正考虑它的情况下隐藏界面这一事实,这是值得考虑的建议。

答案 2 :(得分:5)

1.26 是关于pre-lambda delegate { }语法。

// #1 Empty parenthesis on parameterless-anonymous methods would be:
delegate() { }
// #2 ... anonymous method could have been used on any delegate, is:
delegate { }

请记住,后者可以分配给任何委托,无论其参数如何。委托只是使用一些编译器技巧忽略了这些。

如果您定义一个不带参数的委托,请使用#1明确说明。不要“留下括号,因为你的代表无论如何也不会采用任何参数”。

答案 3 :(得分:4)

很多这些指南都谈到了良好软件设计的“质量属性”(即可维护性,可靠性,可重用性,可测试性,可扩展性,可调试性,互操作性以及您可以命名的其他功能)。

通常人们会创建当时正常工作的代码,但在考虑所有质量属性时(可能是“这个软件将来哪里”或“其他人也必须使用此代码“)。

例如:

  

2.29避免使用三元条件运算符

我对三元表达式本身没有问题,但是通过编写代码如: int result = CheckMethod()? OnTrueDoThis():OnFalseDoThat() ...你说,“我有一个条件,如果是真(或假),你可以做一个而且只有一个。”整个构造阻止可扩展性。您必须重新创建构造(使用if..else语句)。

...类似地

  

2.31避免在布尔条件语句中进行函数调用。分配到   局部变量并检查它们。

您调用了一个函数,并且基本上“丢弃”了结果供以后使用。如果稍后需要该信息,则必须再次调用该函数或者必须重写代码的结构。它还会使检查或记录结果(以便将来的调试)变得更加困难。

享受,

Robert C. Cartaino

答案 4 :(得分:4)

关于1.13(避免使用完全限定的类型名称。请改用“using”语句):

它可能比可读性更重要。如果在文件开头有太多的使用,那么你有一个类与来自太多命名空间的类相结合。

班级正在为重构而尖叫。使用using而不是完全限定的类名可以更轻松地识别这种紧密耦合的类。

答案 5 :(得分:3)

这是我列出的问题的最佳选择。对于那些我不能说的,我省略了。

1.13避免使用完全限定的类型名称。请改用“使用”语句。

可读性。当你必须阅读完全限定的类型名称时,必须更难阅读代码。

2.19避免定义自定义异常类

.NET框架附带了一系列内置于系统中的异常。除非您建模的异常是特定于业务领域的,否则您可能可以使用现有的异常类之一。

2.29避免使用三元条件运算符

我认为这很可能是因为他认为人们可能不了解运营商,但我不同意。

2.47避免与一个成员的接口。

他可能会警告人们构建太薄的界面。但是,我实际上会说反过来,警告人们使接口过于冗长。如果您曾经不得不处理ASP.NET MembershipProvider,那么您就知道我在说什么。

2.31避免在布尔条件语句中进行函数调用。分配到局部变量并检查它们。

我能想到的几个原因。可读性。如果你在其中进行函数调用,它可能使条件语句难以理解。此外,如果你不看,它就更难调试。

2.53更喜欢使用显式接口实现

我相信他的推理是为了简洁起见。但是,我实际上并不同意这种评估。我认为Jon是正确的,应该在可以的时候使用隐式接口,并在适当的时候使用。

答案 6 :(得分:2)

以下是我敢回答的一些反应:)

1.13避免使用完全限定的类型名称。请改用“using”语句。 我不同意。这肯定与性能无关。 可以提高var foo = new Foo()而不是var foo = new MyCompany.MyNamespace.Helpers.Xml.Foo()的可读性,但除此之外 - 没有。

2.19避免定义自定义异常类 这是胡说八道。您应该避免创建从ApplicationException派生的自定义异常,但自定义异常没有任何问题(只要您不打算重新发明现有的异常)。

2.29避免使用三元条件运算符 我不知道为什么那会是一个指导方针。我读过并非所有人都使用它并且可能无法识别它,但这不是不使用有用运算符的正当理由。

2.31避免在布尔条件语句中进行函数调用。分配到局部变量并检查它们。 在我看来,这只是一个可读性问题。

2.47避免与一个成员的接口。 我在这里也不同意。你应该避免使用'marker'接口 - 没有标记的接口,但只是为了某些东西是'...... ble'的目的。但是,界面上的一种方法对我来说似乎很好。

答案 7 :(得分:0)

2.29三元运营商

首先,如果你开始使用三元运算符,那么应该有理由使用三元运算符而不是常规的if-then-else。观察:

if (x == 0) {...} else{...} //A set of statements demand a regular If-then-else

//A simple assignment can be handled by the ternary operator
y = (x == 0)? 1 : 0 //this is readable and how it should be used


(x==0)? callSomething() : callSomethingElse() //this is NOT how it should be used

三元语句用于根据正在评估的条件返回两个值中的一个。这在进行FP时非常方便。对于不返回值的调用语句,您应该恢复为if-then-else。