記錄 編碼約定 學習過程。
命名空間約定
如果沒有使用using指令,項目也沒有默認導入合適的命名空間,訪問這些命名空間或者類型時,則需要“完全限定名稱”。
namespace ConsoleApp4 { class Program { static void Main(string[] args) { // 在這里System.Diagnostics是“完全限定名稱” var traceSource = new System.Diagnostics.TraceSource(""); } } }
如果使用了Using指令,則不需要“完全限定名稱”。
using System.Diagnostics; namespace ConsoleApp4 { class Program { static void Main(string[] args) { var traceSource = new TraceSource(""); } } }
代碼布局約定
- 不輕易更改編輯器的設置,通常使用默認的,特別是格式設置和制表符。
- 每行一條語句,每行一個聲明。
string[] strs = new string[] { "AA","BB","CC"}; string str = "hello"; int num = 4; if (num == 9) { }
- 一行寫不完的語句,斷行寫則需要縮進一個制表符位,除了起頭的第一行,后面無論再斷多少行都是一個制表符位。
string[] strs = new string[] { "AA","BB","CC"}; var query = strs.Where(x => x.Length == 2 && x.Contains("B")). Select(x => new { Name = x, Age = 8 });
- 屬性和方法之間至少一個空行
public int MyProperty { get; set; } public int MyProperty1 { get; set; } void Test() { }
- 使用括號突出表達式的字句。
int val1 = 1; int val2 = 3; int val3 = 4; if ((val1 > val2) && (val1 > val3)) { }
注釋約定
單獨的行,而非代碼末尾;大寫字母開頭,斷行換小寫;句點結束注釋文本;注釋和文本之間留一個空格。
不要在注釋周圍創建格式化的星號塊???沒看懂。
下面放一段ILSpy源碼
/// <summary> /// Sets the value of a dependency property on <paramref name="targetObject"/> using a markup extension. /// </summary> /// <remarks>This method does not support markup extensions like x:Static that depend on /// having a XAML file as context.</remarks> public static void SetValueToExtension(this DependencyObject targetObject, DependencyProperty property, MarkupExtension markupExtension) { // This method was copied from ICSharpCode.Core.Presentation (with permission to switch license to X11) if (targetObject == null) throw new ArgumentNullException(nameof(targetObject)); if (property == null) throw new ArgumentNullException(nameof(property)); if (markupExtension == null) throw new ArgumentNullException(nameof(markupExtension)); var serviceProvider = new SetValueToExtensionServiceProvider(targetObject, property); targetObject.SetValue(property, markupExtension.ProvideValue(serviceProvider)); }
隱式類型var
當明顯可以從賦值右側推導左側變量類型時,使用var。當精確的類型不太重要時,使用var。
var var1 = "This is clearly a string."; var var2 = 27; var var3 = Convert.ToInt32(Console.ReadLine());
右側類型不明確時,則可以聲明一個明確的類型。
using System; namespace ConsoleApp4 { class Program { static void Main(string[] args) { string test = GetObject(2); int test1 = GetObject(1); decimal test2 = GetObject(3); } static dynamic GetObject(int x) { switch (x) { case 1:return 2; case 2:return ""; default:return 8m; } } } }
在for循環使用var,下面的i分別推導為int、decimal。
for (var i = 0; i < 10000; i++) { } for(var i = 0m; i < 10m; i = i + 0.1m) { }
在foreach中不建議使用var。
DataTable dataTable = new DataTable(); // 枚舉值:EnumerableRowCollection<DataRow>,可以推row為DataRow。 foreach (var row in dataTable.AsEnumerable()) { } // 雖然可以推,但聲明明確的類型會讓代碼更加清晰,因為無法在枚舉泛型類型里明顯看出當前row的類型。 foreach (DataRow row in dataTable.AsEnumerable()) { } // 枚舉值:DataRowCollection,不聲明明確類型row則為object?,因此需要聲明明確的類型。 foreach (DataRow row in dataTable.Rows) { }
符號類型
使用時,符號類型優先於無符號類型。short、int、long。 ushort、uint、ulong。
數組
使用間接的語法聲明數組
// 這時候,無法從右側推導變量類型。 string[] vowels1 = { "a", "e", "i", "o", "u" }; // 可以推導,左側使用var var vowels2 = new string[] { "a", "e", "i", "o", "u" }; var vowels3 = new string[2]; vowels3[0] = "a"; vowels3[1] = "e";
委托
使用簡短的語法為委托賦值。
static void Main(string[] args) { Del exampleDel2 = DelMethod; var del3 = new Del(DelMethod); } public delegate void Del(string message); public static void DelMethod(string str) { Console.WriteLine("DelMethod argument: {0}", str); }
Using
如果使用try...finally...,且在finally只有釋放資源的代碼,考慮替換成using,using會自動調用Dispose方法。
Font font1 = new Font("Arial", 10.0f); try { } finally { font1.Dispose(); } using(Font font=new Font("Arial", 10.0f)) { }
New運算符
能推導類型使用var,對象實例的構造函數沒有參數則不必調用構造函數。
// 不必使用new ExampleClass() var instance3 = new ExampleClass { Name = "Desktop", ID = 37414, Location = "Redmond", Age = 2.3 }; var instance4 = new ExampleClass(); instance4.Name = "Desktop"; instance4.ID = 37414; instance4.Location = "Redmond"; instance4.Age = 2.3;
事件處理
在事件比較簡短、且只使用一次的情況下,可以考慮使用lambda表達式。
public Form1() { InitializeComponent(); this.Click += (s, e) => { MessageBox.Show(s.ToString()); }; }
靜態成員
派生對象時,不建議添加和基類具有相同名稱的靜態成員。
using System; namespace ConsoleApp4 { class Program { static void Main(string[] args) { ExampleClass2.Test(); } } class ExampleClass { public static void Test() { Console.WriteLine("調用ExampleClass Test"); } } class ExampleClass2:ExampleClass { // 同名容易引起混亂,隱性覆蓋了ExampleClass的Test方法。 public static void Test() { Console.WriteLine("調用ExampleClass2 Test"); } } class ExampleClass3 : ExampleClass { // 使用new,說明有意覆蓋。 public new static void Test() { } } }
Linq查詢表達式
匿名類型遵循Pascal大小寫格式(與駱駝命名法類似,駱駝命名法是首字母小寫,而Pascal帕斯卡命名法是首字母大寫)。
var localDistributors = from customer in customers join distributor in distributors on customer.City equals distributor.City select new { Customer = customer, Distributor = distributor, CustometorId = customer.ID };
在查詢變量和范圍變量的聲明中使用隱式類型化,雖然查詢變量沒有明確標有var關鍵字,但確實隱式化了。
using System; using System.Linq; namespace ConsoleApp4 { class Program { static void Main(string[] args) { var customers = new System.Collections.Generic.List<Customer>(); var distributors = new System.Collections.Generic.List<Distributor>(); var localDistributors = from customer in customers join distributor in distributors on customer.City equals distributor.City select new { Customer = customer, Distributor = distributor, CustometorId = customer.ID }; } } internal class Distributor { public object City { get; internal set; } } internal class Customer { public object City { get; internal set; } public object ID { get; internal set; } } }
對其from字句下面的查詢語句。
// 第一種:from語句不和聲明變量同一行,則在下一行縮進一個制表符。
var localDistributors = from customer in customers join distributor in distributors on customer.City equals distributor.City select new { Customer = customer, Distributor = distributor, CustometorId = customer.ID };
// 第二種:from語句和聲明變量同一行 var localDistributors = from customer in customers join distributor in distributors on customer.City equals distributor.City select new { Customer = customer, Distributor = distributor, CustometorId = customer.ID };
