Radya Labs C# Coding Style
This document is describe guidelines and recommendations when developing application using C# language. Our main goal is to define a consistent format and style for every source code produced by all Radya Labs developer.
This coding guideline only apply to C# suage and .NET framework common type system. C# is go-to language choice for every project developed by Radya Labs.
###Overview
- Project File : PascalCase
- Source Files : PascalCase
- Other Files : PascalCase
- Namespace : PascalCase
- Class or Struct : PascalCase
- Interface : PascalCase
- Method : PascalCase
- Field : PascalCase, _PascalCase in private
- Constant : PascalCase, _PascalCase in private
- Static Field : PascalCase, _PascalCase in private
- Enum : PascalCase
- Event : PascalCase
- Inline Variable : camelCase
- Parameter : camelCase
###General Guide
- Always use PascalCase and camelCase for name of entity
- Avoid All CAPS and all lowercase for name
- Never declare variables using only case letter difference. Give meaningful name
- Never use name with numeric prefix
- Avoid use numeric suffix in name or identifier
- Always use meaningful and specific name
- Variables and properties should describe an entity, not type or measurement
- Avoid Hungarian Notation!. For example : strName or iCount
- Avoid using abbreviation
- Abbreviation only for common term and widely accepted
- Never use C# keyword for identifier
- Avoid use name that will be potentially conflict with .NET namespace or type
- Avoid redundant prefix or suffix that does not explain more about an identifier.
E.g :
public enum ColorsEnum { }
public class CVehicle { }
public struct RectangleStruct { }- Avoid use parent class name in a property
Customer.Name not Customer.CustomerName- Try to add "Can","Is","Has" prefix to boolean variable
- Add "Average,Count,Sum,Min,Max" in a certain variable that reflect aggregation
###Name and Syntax
Project File
Always use PascalCase that match root namespace name RadyaLabs.csproject -> RadyaLabs.dll -> RadyaLabs
Source File
Always use PascalCase that match class name with file name. Avoid declare several class,enum or delegate in one file. Use descriptive name.
MyClass.cs become
public class MyClass
{ }Resource or Embedded File
Always use PascalCase and descriptive name.
Namespace
Try use PascalCase and name that match project title.
Class
Try use PascalCase. Use noun or noun phrase for class. Add suffix or part of parent class for child class
private class MyClass { }
internal class SpecializedAtribute : Attribute { }
public class CustomerCollection : CollectionBase { }
public class CustomEventArgs : EventArgs { }
private struct ApplicationSettings { }Interface
Try use PascalCase. Always use 'i' prefix for name.
public interface ICustomer
{ }Method
Try use PascalCase. Always use 'i' prefix for name.
public interface ICustomer
{ }Property
Try use PascalCase. Property name should represent an entity. Do not use property name with 'Get' or 'Set' prefix.
public string Name
{
get { }
set { }
}In specific case when property is part of bindable class and an implementation of INotifyPropertyChanged or child class of ModelBase. Always PascalCase, if the API return different format, do formatting with decoration function of JSON.NET
private string _Name;
[JsonProperty(PropertyName = "NAME")]
public string Name
{
get { return _Name; }
set { _Name = value; NotifyPropertyChanged("Name"); }
}Field (Public,Protected, or Internal)
Try use PascalCase. Avoid non-private field. Use property instead.
public string Name;
protected IList InnerList;Field (Private)
Try use PascalCase with underscore (_) prefix.
private string _Name;Constant or static field
Same as field
Enum
Try use PascalCase
public enum CustomerTypes
{
Consumer,
Commercial
}Variables (inline)
Always camelCase.Avoid use single character like 'X' or 'Y' except in loop-block. Avoid using variables name that indicate an order, like text1,text2 or text3
Parameters
Always camelCase
public void Execute(string commandText, int iterations) { }##Coding Style##
###Formatting###
- Never declare more than 1 namespace in a file
- Avoid write more than 1 class in a file
- Always use {} in conditional statement except for one line statement code
- Declare variable separately. Do not declare in one line statement
- Place 3rd library using "using" statement in the beginning of the file
- Group class implementation region according to this order : a. Member b. Constructor c. Nested enums,struct d. Properties e. Methods
- Declare identifier according to this order : a. Private b. Internal c. Protected d. Public
- Group interface implementation using #region directive
- Declare property in different line. This also apply to assembly, method, member and parameter
###Code Commenting###
- All comments should be in same language and include punctuation mark
- Use // or ////
- Do not use "flower box" to mark a comment block
public void Execute(string commandText, int iterations) { }- Use inline comment to explain assumption, issue or an algorithm
- Do not use inline comment to explain obvious code. It should be self-documentted
- Add comment using certain keyword to classify to-do task to ease the reader
//TODO : Please database code here
//UNDONE : Remove this function due to errors
//HACK : Temporary fix until able to refactor- Always use /// to describe a method
/// <summary>
///
/// </summary>##Language Usage## ###General###
- Do not omit the access modifier. Declare identifier explicitly.
//Bad!
void WriteEvent(string message) { }
//Good!
private void WriteEvent(string message) { }###Variables & Types###
- Try to initialize variable when it is declared
- Always choose the simplest of data type
- Always use built-in C# if it is available
short NOT System.Int16
int NOT System.Int32
long NOT System.Int64
string NOT System.String- Always declare member variable as private. Use property for access
- Try to use int type for non-float value
- Only use long for variable that potentially more than the int size
- Try to use double for fractional numeric to ensure decimal precision
- Only use float for numeric fractional that not match with double and decimal
- Only use float if we know the consecuence
- Try to use decimal if we need fractional number that rounded for math.
- Avoid sbyte,short,uint and ulong usage except it is used for interoperability (P/Invoke) with native library
- Avoid numeric usage for magical value for reference. Use constant isntead
- Avoid string usage, use string that come from Resource, cosntant, configuration file and registry
- Only declare constant for simple data type, not for complex type
- Avoid direct casting for object. Use "as" operator and check for null value
- Always to choose generic collection that provided by language feature
- Try to use String.Format() or StringBuilder instead of concatenation operation
- Do not concatenate in a loop
- Do not compare string using String.Empty or "" or use String.Lenght == 0
###Flow Control###
- Avoid recursive function
- Do not modify item in foreach statement
- Avoid boolean validatoin using true or false value
//bad
is (isvalid == true)
{}
//good
if (isvalid)
{}- Avoid assignment in conditional statement
- Use swith/case statement for simple operation
- Use nested if/else instead of switch/case for complex operation
- Try to use polimorphism instead of swich/case
###Other###
- Avoid method usage with more than 5 parameters
- Change parameter methods that more than 5 parameters into object type
##XAML Usage##
- Always use control name that represent its value
<TextBlock x:Name="TextBlockRoomField" Text="ROOMS" FontSize="42"></TextBlock>
<TextBox x:Name="TextBoxRoomValue"/>- Alwayse use method/event handler na me with prefix �On�.
<TextBlock Tap="OnTextBlockRoomFieldTapped" x:Name="TextBlockRoomField" Text="ROOMS" FontSize="42"></TextBlock>