مجموعة من الإرشادات المعقولة في الغالب وأفضل الممارسات لكتابة رمز C# نظيف وقابل للقراءة وقابلة للفهم ويمكن صيانته.
var كلما كان ذلك مناسبًا وممكنًاالغرض: أفضل قابلية للقراءة والنظافة
جيد
var httpClient = new HttpClient ( ) ;سيء
HttpClient httpClient = new HttpClient ( ) ; الغرض: أفضل قابلية للقراءة والنظافة
جيد
var user = new User
{
Username = "admin" ,
Age = 31
} ;سيء
var user = new User ( ) ;
user . Username = "admin" ;
user . Age = 31 ; string.Formatالغرض: قابلية قراءة ودلالات أفضل
جيد
var url = "http://localhost/api" ;
var resource = "users" ;
var path = $ " { url } / { resource } " ;سيء
var url = "http://localhost/api" ;
var resource = "users" ;
var path = string . Format ( "{0}/{1}" , url , resource ) ;الغرض: لا حاجة للهروب
جيد
var path = @"C:UsersAdministratorDocuments" ;سيء
var path = "C: \ Users \ Administrator \ Documents" ;الغرض: يمكن أن تصبح إعادة البناء كابوسًا عندما يتم توزيع حرفيات السلسلة في كل مكان عدة مرات
جيد
const string error = "user_not_found" ;
Log . Error ( error ) ;
return BadRequest ( error ) ;سيء
Log . Error ( "user_not_found" ) ;
return BadRequest ( "user_not_found" ) ; xyz . إنه أمر مثير للسخرية.الغرض: تقصير أسماء المتغيرات لا يضيف أي قيمة ، بل يجعل القراءة والفهم أكثر صعوبة
جيد
// Nice
var validationResult = validator . Validate ( ) ;
// Nice
var stringBuilder = new StringBuilder ( ) ;
// Nice
const string directorySeparator = "/" ;سيء
//
var res = validator . Validate ( ) ;
//
var sbd = new StringBuilder ( ) ;
// Seriously?
const string dsep = "/" ;الغرض: يجعل الكود أسهل بشكل كبير في القراءة والحفاظ عليه والعمل معه
جيد
// The purpose of this class can be easily inferred
public class OrderManager
{
// Using "Is" or "Has" as prefix clearly indicates that a method returns a boolean value
public bool IsFulfilled ( Order order )
{
}
public bool HasPositions ( Order order )
{
}
// Using a verb clearly indicates that a method performs some action
public void ProcessOrder ( Order order )
{
}
public void CancelOrder ( Order order )
{
}
}سيء
// Purpose of this class can not be easily inferred
public class OrderHelper
{
// Unclear
public bool Fulfilled ( Order order )
{
}
// Unclear => users would likely expect a method that retrieves the positions of the order due to the verb "Get"
public bool GetPositions ( Order order )
{
}
// Unclear
public void Order ( Order order )
{
}
// Unclear
public void StopOrder ( Order order )
{
}
}الغرض: يجعل الكود أطول وأصعب بشكل غير ضروري للقراءة والفهم
جيد
// Clearly an interface
public interface IOrderManager { }
// Clearly a list of orders
private IList < Order > orders ;سيء
// Clearly an interface => no "Interface" postfix necessary
public interface IOrderManagerInterface { }
// Clearly a list of oders => no "List" postfix necessary
private IList < Order > orderList ;الغرض: تُظهر الممارسة أن التعليقات يمكن أن تصبح قديمة جدًا وبسرعة مع نمو قاعدة التعليمات البرمجية وتطورها. يساهم وجود قاعدة رمز للشفاء الذاتي في الحفاظ على أفضل وقلل من الحاجة إلى الكتابة والحفاظ على التعليقات غير الضرورية. (هذا لا يعني أن كتابة التعليقات عفا عليها الزمن.)
جيد
public class OrderManager
{
public void ProcessOrder ( Order order )
{
var items = order . GetItems ( ) ;
foreach ( var item in items )
{
var availability = item . GetAvailability ( ) ;
}
}
}سيء
public class OrderManager
{
public void ExecuteOrder ( Order order )
{
// Get all available items from the order
var data = order . GetData ( ) ;
foreach ( var x in data )
{
// Determine the availability of the item
var available = item . CheckAvailability ( ) ;
}
}
}الغرض: بما يتوافق مع إطار .NET وأسهل القراءة
جيد
public class JsonParser { }سيء
public class JSONParser { } الغرض: يتم تناول enum دائمًا بشكل فردي. على سبيل EmploymentTypes.FullTime EmploymentType.FullTime . علاوة على ذلك ، تمثل الفئات دائمًا مثيلًا واحدًا لكائن ، على سبيل المثال User فردي. الاستثناء: التعدادات الحقل بت
جيد
public enum EmploymentType
{
FullTime ,
PartTime
}
public class User
{
}سيء
public enum EmploymentTypes
{
FullTime ,
PartTime
}
public class Users
{
} الغرض: السكر النحوي ¯ (ツ) /¯
جيد
public class User
{
public string Username { get ; }
public int Age { get ; }
public string DisplayName => $ " { Username } ( { Age } )" ;
public User ( string username , int age )
{
Username = username ;
Age = age ;
}
}سيء
public class User
{
public string Username { get ; }
public int Age { get ; }
public string DisplayName
{
get
{
return $ " { Username } ( { Age } )" ;
}
}
public User ( string username , int age )
{
Username = username ;
Age = age ;
}
} الغرض: وعي أفضل لما حدث. يسمح بمزيد من الدقة أثناء التسجيل وتحليل الخطأ.
جيد
try
{
System . IO . File . Open ( path ) ;
}
catch ( FileNotFoundException ex )
{
// Specific
}
catch ( IOException ex )
{
// Specific
}
catch ( Exception ex )
{
// Default
}سيء
try
{
System . IO . File . Open ( path ) ;
}
catch ( Exception ex )
{
// SOMETHING went wrong
}Exception بنفسك الغرض: ممارسة سيئة للغاية. يجب إلقاء Exception فقط بواسطة .NET Framework.
جيد
public void ProcessOrder ( Order order )
{
if ( order == null )
{
throw new ArgumentNullException ( nameof ( order ) ) ;
}
}سيء
public void ProcessOrder ( Order order )
{
if ( order == null )
{
throw new Exception ( "Order is null." ) ;
}
} الغرض: قابلية قراءة أفضل
جيد
private string _username ;سيء
private string mUsername__ ;
// OR
private string username ;
// OR
private string username_ ; الغرض: أفضل للقراءة ، يوفر المساحة
جيد
public class JsonParser
{
private readonly string _json ;
public JsonParser ( string json )
{
_json = json ;
}
}سيء
public class JsonParser
{
private readonly string _json ;
public JsonParser ( string json )
{
_json = json ;
}
} الغرض: يمنع الممتلكات من التغيير عن طريق الخطأ من مكان آخر ، التنبؤ بشكل أفضل لسلوك التطبيق
جيد
public class JsonParser
{
public string Json { get ; }
public JsonParser ( string json )
{
Json = json ;
}
}سيء
public class JsonParser
{
public string Json { get ; set ; }
public JsonParser ( string json )
{
Json = json ;
}
}الغرض: يمنع التجميع من التغيير من مكان آخر ، التنبؤ الأفضل لسلوك التطبيق
جيد
public class KeywordProvider
{
public IReadOnlyCollection < string > Keywords { get ; }
public KeywordProvider ( )
{
Keywords = new ReadOnlyCollection < string > ( new List < string >
{
"public" ,
"string"
} ) ;
}
}سيء
public class KeywordProvider
{
public IList < string > Keywords { get ; }
public KeywordProvider ( )
{
Keywords = new List < string >
{
"public" ,
"string"
} ;
}
} using الكتل الغرض: يتم التخلص using
جيد
using ( var connection = new SqlConnection ( connectionString ) )
{
}سيء
try
{
var connection = new SqlConnection ( connectionString ) ;
}
finally
{
connection . Close ( ) ;
connection . Dispose ( ) ;
} الغرض: قابلية قراءة أفضل ، صيانة أسهل عندما يكون هناك سطر آخر داخل الحالة
جيد
if ( user . IsElevated )
{
// Do something
}سيء
if ( user . IsElevated )
// Do somethingالغرض: بحيث تكون على دراية بأي جزء من الرسالة يحتوي على متغيرات.
جيد
var filePath = @"C:tmpmy-file.txt" ;
try
{
var file = File . Open ( filePath ) ;
}
catch ( Exception ex )
{
// GOOD: Add [ ] to the variable
Log . Error ( $ "Could not open file [ { filePath } ]." , ex ) ;
}سيء
var filePath = @"C:tmpmy-file.txt" ;
try
{
var file = File . Open ( filePath ) ;
}
catch ( Exception ex )
{
Log . Error ( $ "Could not open file { filePath } ." , ex ) ;
}الغرض: بحيث يمكن ترشيح الاستثناء في حالات معينة (على سبيل المثال في واجهة المستخدم ، لأن تتبع المكدس بالكامل غير مجدي للمستخدم).
جيد
try
{
var file = File . Open ( @"C:tmpmy-file.txt" ) ;
}
catch ( Exception ex )
{
// Use appropriate signature of your logger to include the exception as separate parameter
Log . Error ( "Could not open file." , ex ) ;
}سيء
try
{
var file = File . Open ( @"C:tmpmy-file.txt" ) ;
}
catch ( Exception ex )
{
// Strictly AVOID this. The exception is added directly to the log message, which makes it impossible to filter the exception
Log . Error ( $ "Could not open file: { ex } " ) ;
}