[译]C#应用程序开发的一些最佳实践(解释)
By robot-v1.0
本文链接 https://www.kyfws.com/best-practices/some-best-practices-for-c-application-developmen-zh/
版权声明 本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
- 20 分钟阅读 - 9804 个词 阅读量 0[译]C#应用程序开发的一些最佳实践(解释)
原文地址:https://www.codeproject.com/Articles/118853/Some-Best-Practices-for-C-Application-Developmen
原文作者:Kunal Chowdhury «IN»
译文由本站 robot-v1.0 翻译
前言
In this article, I will discuss about C# Best Coding Practices in detail. 在本文中,我将详细讨论C#最佳编码实践.
介绍(Introduction)
几天前,在我较早的一篇文章中,我列出了"(Few days ago, in one of my earlier posts, I listed “) C#应用程序开发的一些最佳实践(Some Best Practices for C# Application Development) “基于我过去的几年经验,深受读者的欢迎.我也对此有很多反馈.我的许多读者也提供了宝贵的建议.在本文中,我将讨论其中的大多数观点.我将使用新的最佳编码惯例定期更新本文.希望我也能在这里获得更多反馈和/或建议.让我们开始讨论C#应用程序开发的最佳编码实践.这里是其中的一些:(” from my past few years experience, which got a huge hit by my readers. I got a lot of feedback on that too. Many of my readers gave valued suggestions too. In this article, I will discuss most of those points. I will keep this article regularly updated with new best coding practices. Hope I will get more feedback and/or suggestions here too. Let’s start discussing the Best Coding Practices of C# application development. Here are some of them:)
使用正确的命名约定(Use Proper Naming Conventions)
您应该选择适当的命名约定,以确保代码的一致性.如果在整个解决方案中使用一致的命名,则维护代码非常容易. .NET开发人员通常遵循以下一些命名约定:(You should prefer proper naming conventions for consistency of your code. It is very easy to maintain the code if consistent naming is used all over the solution. Here are some naming conventions which are generally followed by .NET developers:)
- 在声明变量时,请始终使用Camel大小写(一个单词的首字母小写,随后每个单词的首字母大写).(Always use Camel case (A word with the first letter lowercase, and the first letter of each subsequent word-part capitalized) while declaring variables.)
- 在声明"属性"时,使用Pascal(首字母大写,随后每个单词部分首字母大写的单词)命名格式.(Use Pascal (A word with the first letter capitalized, and the first letter of each subsequent word-part capitalized) naming format while declaring Properties.)
- 避免为属性,变量或方法名称使用所有大写或小写名称.声明const变量时,请全部使用大写字母.(Avoid all uppercase or lowercase names for properties, variables or method names. Use all uppercase when declaring const variables.)
- 切勿使用以数字字符开头的名称.(Never use a name that begins with a numeric character.)
- 对于类,属性,方法等,请始终使用有意义的名称.这对于以后维护代码非常有用.例如,” P"将不会为类赋予适当的含义.您会发现很难了解该课程.但是,如果您使用"人员",则将很容易理解.(Always prefer meaningful names for your class, property, method, etc. This will be very useful for you to maintain the code in future. For example, “P” will not give proper meaning for a class. You will find it difficult to know about the class. But if you use “Person”, you will easily understand by it.)
- 切勿建立大小写不同的其他名称.这是非常不好的做法.在开发代码时,它将不会有用,因为您将不知道什么是"人"类以及什么是"人"类!但是从上述情况来看,很容易理解"人"是"人"类的实例变量.(Never build a different name varied by capitalization. It is a very bad practice. It will not be useful while developing code, as you will not know what is “person” class and what is “Person” class!!! But from the above scenario, it can be very easily understandable that “person” is an instance variable of “Person” class.)
- 请勿使用.NET Framework中使用的相同名称.刚接触您的代码的人很难轻松理解它.(Don’t use the same name used in .NET Framework. People who are new to your code have great difficulty to understand it easily.)
- 避免为标识符添加前缀或后缀.尽管在某些准则中,它们使用" m_",而在另一些准则中,它们使用" _“作为变量声明的前缀.我认为这没什么用.但是,这取决于您的组织编码实践.基于各种组织的观点是矛盾的,对此没有严格的指导.(*Avoid adding prefixes or suffixes for your identifiers. Though in some guidelines, they use “m_” and in some other they use “_” as the prefix of variable declaration. I think it is not that much useful. But, it depends on your organizational coding practices. This point is contradictory based on various organizations and there is no strict guidance on it.*)
- 始终使用” I"作为接口的前缀.这是声明接口的常见做法.(Always use “I” as prefix for Interfaces. This is a common practice for declaring interfaces.)
- 始终为自定义异常类添加" Exception"作为后缀.它将为您的异常类提供更好的可见性.(Always add “Exception” as suffix for your custom exception class. It will give better visibility to your exception class.)
- 切勿在类名的属性名前添加前缀或后缀.它将不必要地增加属性名称.如果"(Never prefix or suffix the class name to its property names. It will unnecessarily increase the property name. If “)
Firstname
“是”(” is a property of “)Person
“类,您可以直接从该类中轻松识别它.无需写”(” class, you can easily identify it from that class directly. No need to write “)PersonFirstname
" 要么 “(” or “)FirstnameOfPerson
“.(”.) - 字首 “(Prefix “)
Is
“,"(”, “)Has
" 要么 “(” or “)Can
“来表示布尔属性,例如”(” for boolean properties like “)IsVisible
“,"(”, “)HasChildren
“,"(”, “)CanExecute
“.这些赋予属性适当的含义.(”. These give proper meaning to the properties.) - 不要为控件添加前缀,而要写适当的名称来标识控件.(Don’t add prefix for your controls, instead write proper name to identify the control.)
在值类型和引用类型之间决定(Decide between Value Types and Reference Types)
每当您需要创建类型时,首先问自己一个问题:“您想要什么,为什么想要它?".如果您可以回答问题,则可以在要使用的类型之间进行选择.如果要存储数据,请使用值类型,当您想通过定义行为来创建类型的实例时,请使用引用类型.值类型不是多态的,而引用类型可以是.就引用类型的内存利用率而言,值类型最高效,并且产生的帮助碎片和垃圾较少.如果要将值传递给方法实现,请确定要执行的操作,并根据需要在值类型和引用类型之间进行选择.使用引用类型的变量实际上会更改原始值,但是使用值类型将创建原始变量的副本并遍历该方法.因此,它可以保护您的原始价值免遭意外更改.让我们在实际示例中查看它们.在下面的代码中,我们传递了变量”(Whenever you need to create a type, first ask yourself a question “What you want and Why you want it?”. If you could answer your question, you can decide between the type you want to use. If you want to store your data, use value types and when you want to create an instance of your type by defining the behavior, use reference types. Value types are not Polymorphic whereas, the Reference types can be. Value types are most efficient in terms of memory utilization over reference types and produce less help fragmentation & garbage. If you want to pass values to a method implementation, decide what you want to do and based upon your requirement, decide between value types and reference types. Use of reference type variables actually change the original value but use of value type will create a copy of the original variable and pass across the method. Thus, it protects your original value from accidental changes. Let’s see them in real example. In the below code, we are passing the variable “) i
“作为值类型,并在方法实现中将其递增(” as value type and in the method implementation incrementing it by) 10
.当它通过值传递时,您将看到原始值”(. As it was passed by value, you will see the original value “) 5
“作为程序代码的输出.(” as output of the program code.)
static void Main(string[] args)
{
int i = 5;
SetValues(i);
System.Console.WriteLine("Currently i = " + i); // will print "Currently i = 5"
}
static void SetValues(int x)
{
x += 10;
}
在下面的代码中,当我们发送”(In the below code, as we are sending “) i
“作为参考,它将更改”(” as a reference, it will change the original value of “) i
“方法中,因此您将看到(” inside the method and hence you will see) 15
作为屏幕中的输出.(as the output in the screen.)
static void Main(string[] args)
{
int i = 5;
SetValues(ref i);
System.Console.WriteLine("Currently i = " + i); // will print "Currently i = 15"
}
static void SetValues(ref int x)
{
x += 10;
}
因此,在开始实施之前先决定,否则一旦实施,将很难在庞大的应用程序上进行更改.(Hence, decide before you start the implementation, else once implemented it will be very difficult to change them over your huge application.)
始终使用属性而不是公共变量(Always Use Properties instead of Public Variables)
其背后的原因是,它使您的代码正确封装在OOPs环境中.通过使用getter和setter,可以限制用户直接访问成员变量.您可以明确限制设置值,从而保护数据免遭意外更改.此外,属性使您可以更轻松地验证数据.让我们看一个小代码:(Reason behind this is, it makes your code properly encapsulated in OOPs environment. By using getters & setters, you can restrict the user directly accessing the member variables. You can restrict setting the values explicitly thus making your data protected from accidental changes. Also, properties give you easier validation for your data. Let’s see a small code:)
public class Person
{
public string name;
public string GetNameInLowerCase()
{
return string.IsNullOrWhiteSpace(name) ?
string.Empty : name.ToLower();
}
public string GetNameInUpperCase()
{
return string.IsNullOrWhiteSpace(name) ?
string.Empty : name.ToUpper();
}
}
在上面的示例中,您将看到必须每次检查(In the above example, you will see you have to check every time for the) Null
值,因为外部人员很容易意外更改值并在代码中创建错误.如果您不希望代码中出现该Bug,您将要做的就是使用变量的属性实现((value as somebody from outside can easily change the value accidentally and create a Bug in your code. If you don’t want that Bug in your code, what you will do is, use the property implementation of the variable (making it) private
),然后访问该属性.这样可以提高代码的可靠性.让我们来看一个例子:() and then access the property. This gives more reliability over your code. Let’s see an example:)
public class Person
{
public string name;
public string Name
{
get
{
return string.IsNullOrWhiteSpace(name) ? string.Empty : name;
}
set { name = value; }
}
public string GetNameInLowerCase()
{
return Name.ToLower();
}
public string GetNameInUpperCase()
{
return Name.ToUpper();
}
}
现在,在这种情况下,您不必考虑根据(Now in this case, you don’t have to think about checking the value against) Null
每次.属性的getter实现将解决这个问题.因此,一次实现可在多个地方使用.因此,如果有人明确设置了”(every time. The getter implementation of the property will take care of it. So, once implementation but use in multiple places. So, if someone explicitly sets the “) Name
“属性(” property to) null
,您的代码对此不会有任何影响.这只是一个示例代码,与您讨论有关属性的需求,而不是(, your code will have no impact on it. This is just a sample code to discuss with you about the need of property instead of) public
成员变量.实际的实现可能会根据您的要求而有所不同.(member variable. Actual implementation may vary based on your requirement.)
public class Person
{
public string Name { get; private set; }
public string Age { get; }
}
如果您不希望任何人从外部显式设置Property,则只能在属性实现内部实现getter或将setter标记为(If you don’t want anybody to set the Property explicitly from outside, you can just only implement the getter inside the property implementation or mark the setter as) private
.另外,您可以从任何接口实现属性,从而为您提供更多的OOPs环境.(. Also, you can implement the properties from any interface, thus gives you more OOPs environment.)
必要时使用可空数据类型(Use Nullable Data Types Whenever Required)
有时,您可能需要存储(Sometimes, you may need to store) null
作为整数,双精度或布尔变量的值.那你怎么做呢?普通声明不允许您存储(as the value of an integer, double or boolean variable. So how can you do this? The normal declaration doesn’t allow you to store the) null
作为价值. C#现在具有可为空的数据类型的功能.声明中的一个小改动.而已!!!你很好去储存(as value. C# now has the feature of nullable data types. Just a small change in your declaration. That’s it!!! You are good to go for storing) null
价值观.只有您必须使用”?“修饰符.您必须将其放置在类型之后.要定义整数,通常需要执行以下声明:(values. Only you have to use the “?” modifier. You have to place it just after the type. To define an integer, you would normally do the following declaration:)
int index = 0; // simple declaration of int
要将其转换为可为空的数据类型,您必须进行如下修改以声明:(To convert this as an nullable data type, you have to modify a bit to declare like this:)
int? index = null; // nullable data type declaration
一旦添加”?“修改数据类型,您的变量将变为可为空,并且您将能够存储”(Once you add the “?” modifier to the data type, your variable will become nullable and you will be able to store “) null
值.通常,与布尔值一起使用时会很有帮助.(” value to it. Generally it is helpful when used with the boolean values.)
运行时常量胜于编译时间常量(Prefer Runtime Constants over Compile time Constants)
运行时常数总是比编译时常数更可取.在这里,您可能会问什么是运行时常数,什么是编译时间常数.运行时常量是在运行时求值并用关键字”(Runtime constants are always preferred than the Compile time constants. Here you may ask what is runtime constant and what is compile time constant. Runtime constants are those which are evaluated at the runtime and declared with the keyword “) readonly
“.另一方面,编译时间常数为(”. On the other side, compile time constants are) static
,在编译时进行评估,并使用关键字”(, evaluated at the time of compilation and declared with the keyword “) const
“.(”.)
public readonly string CONFIG_FILE_NAME = "web.config"; // runtime constant
public const string CONFIG_FILE_NAME = "web.config"; // compile time constant
那么,有什么需要偏爱的(So, what is the need to prefer) readonly
过度(over) const
变量?编译时间常数((variables? Compile time constants () const
)必须在声明时进行初始化,以后不能更改.而且,它们仅限于数字和字符串. IL取代了() must be initialized at the time of declaration and can’t be changed later. Also, they are limited to only numbers and strings. The IL replaces the) const
在整个代码中包含变量的值,因此速度要快一些.而运行时常量(只读)在构造函数中初始化,并且可以在不同的初始化时间进行更改. IL引用只读变量,而不是原始值.因此,当您遇到紧急情况时,请使用(variable with the value of it over the whole code and thus it is a bit faster. Whereas, the Runtime constants (readonly) are initialized in the constructor and can be changed at different initialization time. The IL references the readonly variable and not the original value. So, when you have some critical situation, use) const
使代码运行更快.当您需要可靠的代码时,总是喜欢(to make the code run faster. When you need a reliable code, always prefer) readonly
变量.(variables.)
投放时更喜欢” is"和” as"运算符(Prefer “is” and “as” Operators While Casting)
最好使用”(It is better to use “) is
“和”(” and “) as
投放时操作”.代替显式强制转换,请使用隐式强制转换.让我用代码示例向您描述.(” operator while casting. Instead of Explicit casting, use the Implicit casting. Let me describe to you with the example of a code.)
// this line may throw Exception if it is unable to downcast from Person to Employee
var employee = (Employee) person;
在上面的代码中,假设您的人是(In the above code, suppose your person is a) Customer
类型以及将其转换为(type and when you are converting it to) Employee
类型,它将抛出(type, it will throw) Exception
在这种情况下,您必须使用(and in that case, you have to handle it using) try{} catch{}
块.让我们使用”(block. Let’s convert the same using “) is
“和”(” and “) as
“运算符.请参见以下代码:(” operators. See the below code:)
// check if the person is Employee type
if(person is Employee)
{
// convert person to Employee type
employee = person as Employee;
}
// check if the person is Customer type
else if(person is Customer)
{
// convert person to Customer type
customer = person as Customer;
}
在上面的代码中,您可以看到,在第二行中,我正在检查此人是否是(In the above code, you can see that, in the second line I am checking whether the person is a) Employee
类型.如果是类型(type. If it is of type) Employee
,它将进入该区块.否则,如果(, it will go into the block. Else if it is a) Customer
类型,将转到第12行的代码段.现在,使用”(type, will go to the block at line 12. Now, convert it with the “) as
“运算子,如第5行所示.此处,如果无法转换,它将返回为(” operator, as shown in line 5. Here, if it is unable to convert, it will return as) null
但不会引发任何异常.因此,在下一行中,您可以检查转换后的值是否为(but will not throw any exception. So, in the next line, you can check whether the converted value is) null
.基于此,您可以做自己想做的.(. Based on that, you can do what you want.)
首选使用string.Format()或StringBuilder进行字符串连接(Prefer string.Format() or StringBuilder for String Concatenation)
中的任何操作(Any operation in the) string
将创建一个新对象(will create a new object as) string
是一个可变的对象.如果要串联多个(is a mutable object. If you want to concatenate multiple) string
s,总是更好用(s, it is always better to use) string.Format()
方法或(method or) StringBuilder
串联的类.(class for the concatenation.)
string str = "k";
str += "u";
str += "n";
str += "a";
str += "l";
Console.WriteLine(str);
的情况下(In case of) string.Format()
,它将不会创建多个对象,而只会创建一个对象.(, it will not create multiple objects instead will create a single one.) StringBuilder
因为不可变的对象不会为每个操作创建单独的内存.因此,您的应用程序内存管理将不会处于关键阶段.因此,总是最好使用(as an immutable object will not create separate memory for each operation. So your application memory management will not be in critical stage. Hence, it is always preferable to do such operations either using) string.Format()
要么(or) StringBuilder
.(.)
上面的代码将创建一个新的(The above code will create a new) string
每当我们添加新对象时(object whenever we add a new) string
那里.使用(there. Using) string.Format()
,您可以编写以下代码:(, you can write the following code:)
string str = string.Format("{0}{1}{2}{3}{4}", "k", "u", "n", "a", "l");
如果要使用(If you want to use) StringBuilder
,这是适合您的代码:(, here is the code for you:)
StringBuilder sb = new StringBuilder();
sb.Append("k");
sb.Append("u");
sb.Append("n");
sb.Append("a");
sb.Append("l");
string str = sb.ToString();
以上两个示例将使用相同的(The above two examples will use the same instance of the) string
每次.(every time.)
需要时使用条件属性(Use Conditional Attributes When You Need Them)
当您只想对调试版本进行操作时,条件属性非常有用.我知道您想到了什么(Conditional attributes are very helpful when you want to do something only for the debug version. I know something came into your mind, the) #if
/(/) #endif
块.是的,您可以使用(block. Yes, you can use the) #if
/(/) #endif
块来执行特定于调试版本的操作,例如跟踪或在输出屏幕上打印某些内容.那我们为什么不使用它们呢?当然可以.但是,有一些陷阱.假设您编写了以下代码:(blocks to do something specific to the debug version like tracing or printing something to the output screen. Then why shouldn’t we use them? Of course, you can do that. But, there are some pitfalls. Suppose you wrote the following code:)
private void PrintFirstName()
{
string firstName = string.Empty;
#if DEBUG
firstName = GetFirstName();
#endif
Console.WriteLine(firstName);
}
在这种情况下,它将在调试模式下完美运行.但是,请看另一面.投入生产时,(In this case, it will work perfectly while in debug mode. But, see the other side. When it goes to production, the) GetFirstName()
永远不会被调用,因此它将打印一个空白(will never get called and hence it will print an empty) string
.那将是您代码中的错误.那么该怎么办?我们可以使用条件属性来克服此问题.在方法中编写代码,并使用DEBUG字符串设置Conditional类型的属性.当您的应用程序以调试模式运行时,它将调用该方法,而在其他情况下,则不会.让我们在这里查看代码:(. That will be a Bug in your code. So, what to do? We can use the Conditional Attribute to overcome this issue. Write your code in a method and set the attribute of type Conditional with DEBUG string. When your application runs in debug mode, it will call the method and in other case, it will not. Let’s see the code here:)
[Conditional("DEBUG")]
private void PrintFirstName()
{
string firstName = GetFirstName();
Console.WriteLine(firstName);
}
上面的代码实际上使用(The above code actually isolates the function with the) Conditional
属性.如果您的应用程序在调试版本下运行,它将加载(attribute. If your application is running under debug build, it will load the) PrintFirstName()
第一次调用时进入内存.但是当它进入生产版本(即发布版本)时,该方法将永远不会被调用,因此不会被加载到内存中.一旦获得方法的条件属性,编译器将处理该做什么.因此,始终建议使用条件属性而不是(into memory on the first call to it. But when it will go to production build (i.e. release build) the method will never get called and hence it will not be loaded into memory. The compiler will handle what to do once it gets the conditional attribute to the method. Hence, it is always advisable to use the conditional attribute instead of the) #if
实用程序块.(pragma blocks.)
[Conditional("DEBUG")]
[Conditional("TRACE")]
private void PrintFirstName()
{
string firstName = GetFirstName();
Console.WriteLine(firstName);
}
另外,如果要设置多个条件属性,则可以通过添加多个属性来做到这一点,如上所示.(Also, if you want to set multiple conditional attributes, you can do that by adding multiple attributes as shown above.)
使用” 0”(零)作为默认值枚举值类型(Use ‘0’ (zero) as Default Value Enum Value Types)
当我们写(While we write the) enum
定义,有时我们错过了设置(definition, sometime we miss to set the) DEFAULT
有价值.在这种情况下,它将自动设置为(value to it. In that case, it will set automatically as) 0
(零).((zero).)
public enum PersonType
{
Customer = 1
}
class Program
{
static void Main(string[] args)
{
PersonType personType = new PersonType();
Console.WriteLine(personType);
}
}
例如,上面的代码将始终打印(For example, the above code will always print) 0
(零)作为输出,您必须为其显式设置默认值.但是,如果我们稍作更改并添加默认值,它将始终打印默认值,而不是((zero) as output and you have to explicitly set the default value for it. But if we change it a bit and add the default value, it will always print the default value instead of) 0
(零).((zero).)
public enum PersonType
{
None = 0,
Customer = 1
}
class Program
{
static void Main(string[] args)
{
PersonType personType = new PersonType();
Console.WriteLine(personType);
}
}
在这种情况下,它将打印”(In this case, it will print “) None
“到输出屏幕.实际上,系统会将值类型的所有实例初始化为(” to the output screen. Actually the system initializes all instances of value type to) 0
.无法阻止用户创建所有值类型的实例(. There is no way to prevent users from creating instance of value type that are all) 0
(零).因此,始终建议将默认值隐式设置为((zero). Hence, it is always advisable to set the default value implicitly to the) enum
类型.(type.)
总是更喜欢foreach(…)循环(Always Prefer the foreach(…) Loop)
的(The) foreach
陈述是(statement is a variation of) do
,(,) while
要么(or) for
循环.实际上,它会为您拥有的任何集合生成最佳的迭代代码.使用收藏集时,请始终喜欢使用(loops. It actually generates the best iteration code for any collection you have. When you are using collections, always prefer to use the) foreach
循环,因为C#编译器会为您的特定集合生成最佳的迭代代码.看一下以下实现:(loop as the C# compiler generates the best iteration code for your particular collection. Have a look into the following implementation:)
foreach(var collectionValue in MyCollection)
{
// your code
}
在这里,如果你的(Here, if your) MyCollection
是一个(is an) Array
类型,C#编译器将为您生成以下代码:(type, the C# compiler will generate the following code for you:)
for(int index = 0; index < MyCollection.Length; index++)
{
// your code
}
以后,如果您将集合类型更改为(In future, if you change your collection type to) ArrayList
代替(instead of) Array
,(, the) foreach
循环仍将编译并正常工作.在这种情况下,它将生成以下代码:(loop will still compile and work properly. In this case, it will generate the following code:)
for(int index = 0; index < MyCollection.Count; index++)
{
// your code
}
只需检查(Just check the) for
健康)状况.您会在那看到一点区别.(condition. You will see a little difference there.) Array
具有(has) Length
属性,因此它生成了调用(property and hence it generated code which calls the) Length
.但是在(. But in case of) ArrayList
,它取代了(, it replaced the) Length
与(with) Count
,作为(, as) ArrayList
具有(has) Count
做同样的事情.在其他情况下,如果您的集合类型实现(which does the same thing. In other scenario, if your collection type implements) IEnumerator
,它将为您生成一个不同的代码.让我们看一下代码:(, it will generate a different code for you. Let’s see the code:)
IEnumerator enumerator = MyCollection.GetEnumerator();
while(enumerator.MoveNext())
{
// your code
}
因此,您不必考虑使用哪个循环.编译器对此负责,它将为您选择最佳循环.的另一优势(Hence, you don’t have to think which loop to use. The compiler is responsible for that and it will choose the best loop for you. One more advantage of) foreach
loop是在单维或多维数组中循环.如果是多维数组,则不必写多行(loop is while looping through the Single Dimensional or Multi Dimensional array. In case of Multi Dimensional array, you don’t have to write multi line) for
陈述.因此,它将减少您必须编写的代码.编译器将在内部生成该代码.因此,可以提高您的生产率.(statements. Hence, it will reduce the code you have to write. The compiler internally will generate that code. Thus, increases your productivity.)
正确利用try/catch/finally块(Properly Utilize try/catch/finally Blocks)
是的,正确利用(Yes, properly utilize the) try
/(/) catch
/(/) finally
块.如果您知道编写的代码可能会引发某些异常,请使用(blocks. If you know that the code you wrote may throw some Exception, use the) try
/(/) catch
阻止该段代码处理异常.如果您知道,第10行代码的第五行可能会引发异常,建议仅用(block for that piece of code to handle the exception. If you know that, the fifth line of your 10 lines code may throw exception, it is advisable to wrap that line of code only with the) try
/(/) catch
块.不必要的代码行与(block. Unnecessary surrounding lines of code with) try
/(/) catch
将减慢您的应用程序.有时,我注意到人们围绕着每种方法(will slow down your application. Sometimes, I noticed people surrounding every method with) try
/(/) catch
块,这确实非常糟糕,并降低了代码的性能.因此,从现在开始,仅在需要时使用它.使用(block which is really very bad and decreases the performance of the code. So from now, use it only when it is required. Use the) finally
调用后阻止清理所有资源.如果正在执行任何数据库调用,请在该块中关闭连接.的(block to clean up any resources after the call. If you are doing any database call, close the connection in that block. The) finally
无论您的代码是否正确执行,block都会运行.因此,请适当利用它来清理资源.(block runs whether your code executes properly or not. So, properly utilize it to cleanup the resources.)
仅捕获您可以处理的异常(Catch Only that Exception that You Can Handle)
这也是主要的.人们总是使用通用(It is also a major one. People always use the generic) Exception
类捕获任何不利于您的应用程序或系统性能的异常.只捕获您期望的那些并相应地订购.最后,如果需要,最后添加通用(class to catch any exception which is neither good for your application nor for the system performance. Catch only those which you expect and order it accordingly. Finally at the end, if you want, add the generic) Exception
捕获任何其他未知异常.这为您提供了处理异常的正确方法.假设您的代码正在抛出(to catch any other unknown exceptions. This gives you a proper way to handle the exception. Suppose, your code is throwing) NullReferenceException
要么(or) ArgumentException
.如果您直接使用(. If you directly use the) Exception
类,在您的应用程序中将很难处理.但是通过正确捕获异常,您可以轻松解决问题.(class, it will be very difficult to handle in your application. But by catching the exception properly, you can handle the problem easily.)
使用IDisposable接口(Use IDisposable Interface)
用(Use) IDisposable
接口从内存中释放所有资源.一旦实施(interface to free all the resources from the memory. Once you implement) IDisposable
课堂上的界面,您将获得一个(interface in your class, you will get a) Dispose()
方法在那里.在此处编写代码以释放资源.如果实施(method there. Write code there to free the resources. If you implement) IDisposable
,您可以像这样初始化您的类:(, you can initialize your class like this:)
using (PersonDataSource personDataSource = DataSource.GetPerson())
{
// write your code here
}
之后(After the) using() {}
块,它将调用(block, it will call the) Dispose()
方法自动释放类资源.您无需致电(method automatically to free up the class resources. You will not have to call the) Dispose()
明确地为班级.(explicitly for the class.)
用几种简单的方法拆分逻辑(Split your Logic in Several Small and Simple Methods)
如果方法太长,有时很难处理.始终最好根据其功能使用许多小型方法,而不是将它们放在一个方法中.如果将它们分解为单独的方法,并且将来需要调用一个部件,则调用将比复制代码更容易.同样,对小块而不是大代码进行单元测试也更容易.因此,每当编写一段代码时,首先要考虑您想做什么.基于此,请使用简单的小型方法提取代码,然后从所需位置调用它们.通常,一种方法的长度不应超过10-15行.(If methods are too long, sometimes it is difficult to handle them. It is always better to use a number of small methods based upon their functionality instead of putting them in a single one. If you break them in separate methods and in future you need to call one part, it will be easier to call rather than replicating the code. Also, it is easier to do unit testing for the small chunks rather than a big code. So, whenever you are writing a piece of code, first think of what you want to do. Based upon that, extract your code in small simple methods and call them from wherever you want. In general, a method should never be more than 10-15 lines long.)
尾注(End Note)
希望这些要点将帮助您正确理解C#编码实践.还有更多我没有在这里讲的要点.我将很快在同一主题中发布它们.如果您有任何建议或意见,请告诉我.干杯…(Hope these points will help you to understand the C# coding practices properly. There are more points which I didn’t cover here. I will publish them soon in the same thread. If you have any suggestion or comments, please let me know. Cheers…)
许可
本文以及所有相关的源代码和文件均已获得The Code Project Open License (CPOL)的许可。
C# C#4.0 C#3.0 .NET3.5 .NET .NET4 .NET3.0 Dev 新闻 翻译