출처 : https://docs.google.com/document/d/13N-08EAVkeKkhWVxyh6UMEzVL6KwwXLT4aPV4uoqvMw/edit#
C# 코딩 표준
원문(영어): C# Coding Standards 머리말 기본 원칙 가독성을 최우선으로 삼는다. (대부분의 경우 코드는 그 자체가 문서의 역할을 해야 함) 정말 합당한 이유가 있지 않는 한, 통합개발환경(IDE)의 자동 서식을 따른다. (비주얼 스튜디오의 “Ctrl + K + D” 기능) 본 코딩표준을 따라 잘 짜여진 기존의 코드에서 배운다. 참조문서 이 코딩 표준은 아래의 코딩 표준들에서 영감을 얻었음. 언리얼 엔진 4 코딩 표준 둠 3 코드 스타일과 규칙 IDesign C# 코딩 표준 IDE 도우미 비주얼 스튜디오에 ...
docs.google.com
머리말
기본 원칙
1. 가독성을 최우선으로 삼는다.(대부분의 경우 코드는 그 자체가 문서의 역할을 해야 함)
2. 정말 합당한 이유가 있지 않는 한, IDE의 자동 서식을 따른다. (비쥬얼 스튜디오 Ctrl + K + D)
3. 본 코딩표준을 따라 잘 짜여진 기존의 코드에서 배운다.
명명 규칙과 스타일
클래스와 구조체의 이름은 파스칼 표기법을 따른다
단어 앞 글자는 "대문자"
class PlayerManager;
struct PlayerData;
지역 변수 그리고 함수의 매개 변수의 이름은 카멜 표기법을 따른다
단어 앞 글자는 "소문자", 합성 단어는 뒷 단어의 앞 글자만 "대문자"
public void SomeMethod(int someParam)
{
int someNumber;
int id;
}
메서드 이름은 동사-명사의 형태로 짓는다
public uint GetAge()
{
// 함수 구현부
}
public 메서드가 아니면 카멜 표기법을 따른다
public은 파스칼 표기법을 따른다
public uint GetAge()
{
// 함수 구현부
}
uint getAget()
{
// 함수 구현부
}
상수의 이름은 모두 대문자로 하되 밑줄로 각 단어를 분리한다
const int SOME_SONSTANT = 1;
상수로 사용하는 개체형 변수에는 static readonly를 사용한다
public static readonly MY_CONST_OBJECT = new MyConstClass();
static readonly 변수는 모두 대문자로 하되 밑줄로 각 단어를 분리한다
초기화 후 값이 변하지 않는 변수는 readonly로 선언 한다}
public class Account
{
private readonly string mPassword;
public Accout(string password)
{
mPassword = password;
}
}
네임스페이스의 이름은 파스칼 표기법을 따른다
namespace System.Graphics
부울(boolean)변수는 앞에 b를 붙이며, 부울 프로퍼티는 앞에 Is를 붙인다
bool bFired; // 지역 변수(b)
private bool mbFired; // private 멤버 변수(mb)
public bool IsFired { get; private set; } // 프로퍼티(Is)
인터페이스를 선언 할 때에는 앞에 I를 붙인다
interface ISOmeInterface;
열거형을 선언 할 때에는 앞에 E를 붙인다
public enum EDirection
{
North,
South
}
private 멤버 변수명은 앞에 m을 붙이고 파스칼 표기법을 따른다
public class Employee
{
public int DepartmentID { get; set; }
private int mAge;
}
반환값이 있는 함수는 이름만 봐도 무엇을 반환 하는지 알 수 있어야 한다
public uint GetAge();
단순 반복문에 사용되는 변수가 아니라면 i, j 말고 변수에 저장된 데이터를 알 수 있는 변수명을 사용한다
for(int employee = 0; employee <= 100; employee++)
{
if(employee == 50)
...
}
뒤에 추가적인 단어가 오지 않는 경우 줄임말은 모두 대문자로 표기한다
public int OrderID { get; private set; }
public int HttpCode { get; private set; }
getter와 setter 대신 프로퍼티를 사용 한다
틀린 방식
public class Employee
{
string mName;
public string GetName();
public string SetName(string name);
}
올바른 방식
public class Employee
{
public string Name { get; set; }
}
지역 변수를 선언 할 때는 그 지역 변수를 사용하는 코드와 동일한 줄에 선언 하는 것을 원칙으로 한다
중괄호 { }를 열 때는 언제나 새로운 줄에 연다
중괄호 { }에 코드가 한 줄만 있더라도 반드시 중괄호를 사용 한다
if(bSomething)
{
return;
}
switch문에 언제나 default: 케이스를 넣는다
switch(number)
{
case 0:
...
break;
default:
break;
}
switch문에서 default: 케이스가 절대 실행 될 일이 없는 경우 Debug.Fail() 또는 Debug.Assert(false)란 코드를 추가한다
switch(type)
{
case 0:
...
break;
default:
Debug.Fail("unknown type");
break;
}
재귀 함수 이름 뒤에는 Recursive를 붙인다
public void FibonacciRecursive();
클래스 안에서 멤버 변수와 메서드의 등장 순서는 다음을 따른다
public 멤버변수 / 프로퍼티
internal 멤버변수 / 프로퍼티
protected 멤버변수 / 프로퍼티
private 멤버변수 / 프로퍼티
생성자
public 메서드
internal 메서드
protected 메서드
private 메서드
대부분의 경우 함수 오버로딩을 피한다
틀린 방식
public Anim GetAnim(int index);
public Anim GetAnim(string name);
올바른 방식
public Anim GetAnimByIndex(int index);
public Anim GetAnimByName(string name);
클래스는 각각 독립된 소스코드 파일에 있어야 한다
단, 작은 클래스 몇 개를 한 파일 안에 넣어두는 것이 상식적일 경우 제외
파일 이름은 대소문자까지 클래스 이름과 일치 해야한다
public class PlayerAnimation { }
PlayerAnimation.cs
여러 파일이 하나의 클래스를 이룰 때(parital 클래스), 파일 이름은 클래스 이름으로 시작하고 그 뒤에 마침표와 세부 항목 이름을 붙인다
public partial class Human;
Human.Head.cs
Human.Body.cs
Human.Arm.cs
특정 조건이 반드시 충족되어야 한다고 가정(assertion)하고 짠 코드 모든 곳에 assert를 사용한다. assert는 복구 불가능한 조건이다
비트 플래그 열거형은 이름 뒤에 Flags를 붙인다
public enum EVisibilityFlags
{
}
디폴트 매개 변수 대신 함수 오버로딩을 선호한다
디폴트 매개 변수를 사용하는 경우, null이나 false, 0 같이 비트 패턴이 0인 값을 사용한다
변수 가리기(variable shadowing)는 허용되지 않는다. 외부 변수가 동일한 이름을 사용중이라면 내부 변수에는 다른 이름을 사용한다
public class SomeClass
{
public int Count { get; set; }
public void Func(int count)
{
for(int count = 0; count != 10; ++count)
{
// count를 사용
}
}
}
System.Collections의 컨테이너 대신, System.Collections.Generic의 컨테이너를 사용한다
순수 배열을 사용 하는 것도 괜찮다
var 키워드를 사용하지 않으려 노력한다
싱글턴 패턴 대신에 정적(static) 클래스를 사용한다
async void 대신 async Task를 사용한다
async void가 허용되는 유일한 곳은 이벤트 핸들러이다
외부에서 들어오는 데이터의 유효성은 외부/내부 경계가 바뀌는 곳에서 검증하고 문제가 있을 경우 내부 함수로 전달하기 전에 반환 해버린다
이는 경계를 넘어 내부로 들어온 모든 데이터는 유효하다고 가정한다는 뜻
따라서 내부 함수에서 익셉션을 던지지 않으려 노력한다
예외는 경계에서만 처리하는 것을 원칙으로 한다
위 규칙의 예외: enum형을 switch문에서 처리할 때 default: 케이스에서 예외를 던지는 것은 허용
switch (accountType)
{
case AccountType.Personal:
return something;
case AccountType.Business:
return somethingElse;
default:
throw new ArgumentOutOfRangeException(nameof(AccountType));
}
함수의 매개변수로 null을 허용하지 않는다(특히 public 함수)
함수에서 null을 반환 할때 함수이름 뒤에 orNull을 붙인다
public string GetNameOrNull();
object initalizer를 사용하지 않으려고 노력한다
생성자와 이름으로 지정한 매개변수를 사용하는게 더 좋은 방법이다
한 줄에 변수 하나만 선언한다
// 틀린 방식
int counter = 0, index = 0;
// 올바른 방식
int counter = 0;
int index = 0;
'개발언어 > C#' 카테고리의 다른 글
[c#] [StructLayout()]객체의 메모리 레이아웃에 대하여 (0) | 2020.11.04 |
---|---|
[C#] [Flag] Enum Attribute는 무엇을 의미합니까? (0) | 2020.11.04 |
[C#] 고정크기배열 사용방법 #MarshalAs (0) | 2020.11.03 |
[C#] x86/x64 환경에 따라 달라지는 P/Invoke 함수의 export 이름 (0) | 2020.11.03 |
[C#] WinAPI(Kernel32 dll) 사용하기 (0) | 2020.11.03 |