CHashtag

[C#] 코딩 규칙 (Coding Convention) 본문

C#

[C#] 코딩 규칙 (Coding Convention)

HyoSeong 2021. 5. 6. 23:34
반응형

안녕하세요.

 

 

오늘은 C#개발을 할 때에 지켜야 할 규칙에 대해 알려드리려 합니다.

 

오늘 알려드릴 내용은 "권장사항" 입니다.

 

아래 코딩 규칙이 회사, 팀에서 사용하고 코딩 규칙과 다르다면 따르지 않는것을 추천합니다.

 

코딩 규칙이 존재하는 이유는 여러 사람이 일관성있는 코드를 작성할 수 있게 돕고, 그로인해 코드 가독성을 높이기 위함임을 꼭 기억하기시 바랍니다.

 

일관성 있는 코드 작성 -> 가독성 올라감 -> 코드 리딩 및 이해가 빠름 -> 개발시간 단축 및 리팩토링 용이

 

(아래 몇몇 규칙중에서는 성능을 높여주는 규칙도 포함되어 있습니다.)

 

오늘 게시글은 마이크로소프트 공식 문서를 참고하여 예제를 추가한 것입니다.

관련해 더 자세하고 정확한 내용은 원문을 참고해주시기 바랍니다.

(docs.microsoft.com/ko-kr/dotnet/csharp/programming-guide/inside-a-program/coding-conventions)

 


1. 레이아웃 규칙

 

1-1. 문을 한 줄에 하나씩만 작성합니다.


MessageBox.Show("한줄에 하나씩");
MessageBox.Show("코드를 작성합니다.");

 

1-2. 선언을 한 줄에 하나씩만 작성합니다.


string text1 = "선언은 한 줄에 하나씩";
string text2 = "선언은 한 줄에 하나씩";

 

1-3. 연속 줄이 자동으로 들여쓰기되지 않으면 탭 정지 하나(공백 4개)만큼 들여씁니다.


bool canEat = true;

if(canEat)
{
    MessageBox.Show("4칸을 들여씁니다.");
}   

 

1-4. 메서드 정의와 속성 정의 간에는 빈 줄을 하나 이상 추가합니다.


// Tomato 속성과 GetTomato 메서드 정의 사이에 빈 줄을 추가합니다.
public Tomato Tomato { get; set; }

public Tomato GetTomato()
{
    return this.Tomato;
}

 

1-5. 괄호를 사용하여 식의 절을 명확하게 구분합니다.


if ((val1 > val2) && (val1 > val3))
{
    MessageBox.Show("괄호를 사용하면 가독성이 높아집니다.");
}

 

2. 주석 달기 규칙

 

2-1. 코드 줄의 끝이 아닌 별도의 줄에 주석을 배치합니다.


MessageBox.Show("Success!"); // (X) 메세지를 출력한다.

// (O) 메세지를 출력한다.
MessageBox.Show("Success!");

 

2-2. 주석 텍스트는 대문자로 시작합니다.


// I don't know what now I'm talking about.
// 한글 주석은 해당사항이 없습니다.

 

2-3. 주석 텍스트 끝에는 마침표를 붙입니다.


// 주석 텍스트 문장의 끝에는
// 마침표를 붙입니다.

 

2-4. 주석 구분 기호(//)와 주석 텍스트 사이에 공백을 하나 삽입합니다.


//이렇게 붙여서 사용하지 마시고
// 한칸 띄워서 주석을 작성하시면 됩니다.

 

2-5. 서식이 지정된 별표 블록으로 주석을 묶지 않습니다.


//***************************
//* 이런식으로 주석을 작성하지 말라는 뜻입니다. *
//* 예전C, C++에서 이런 스타일의 주석을 작성하였습니다. *
//* 관련 링크 : https://www.reddit.com/r/csharp/comments/am098s/formatted_blocks_of_asterisks_around_comments_in/ *
//***************************

 

3. 문법 관련 규칙

 

3-1. 짧은 문자열을 연결할 때에는 문자열 보간을 사용합니다.


string lastName = "Lee";
string firstName = "HyoSeong";

// $가 앞에 붙는 것이 특징입니다.
// 문자열 보간에 대한 자세한 내용은
// https://docs.microsoft.com/ko-kr/dotnet/csharp/language-reference/tokens/interpolated
// 를 참고하세요.
// 이 기능은 C# 6.0에 추가되었습니다.
string displayName = $"{lastName}, {firstName}";

 

3-2. 많은 양의 텍스트를 사용할 때 문자열을 루프에 추가하려면 StringBuilder 개체를 사용합니다.


var phrase = "lalalalalalalalalalalalalalalalalalalalalalalalalalalalalala";
var manyPhrases = new StringBuilder();
for (var i = 0; i < 10000; i++)
{
    manyPhrases.Append(phrase);
}

 

3-3. 할당 오른쪽에서 변수 형식이 명확하면 암시적 형식을 사용합니다.


var var1 = "이건 누가봐도 문자열입니다.";
var var2 = 27;

 

3-4. 정확한 형식이 중요하지 않으면 지역 변수에 대해 암시적 형식을 사용합니다.


 

3-5. 할당 오른쪽에서 변수 형식이 명확하지 않으면 암시적 형식을 사용하지 않습니다.


// 아래 코드들은 보기에는 명확해 보이지만 명확하지 않은 할당입니다.
// 명확한 할당이란 new 연산자나 명시적 캐스트인 경우 명확한 것으로 간주됩니다.
int var3 = Convert.ToInt32(Console.ReadLine());
int var4 = ExampleClass.ResultSoFar();

 

3-6. 변수 이름을 사용하여 변수 형식을 지정하지 않습니다.


// 형식이 올바르게 지정되지 않을 수 있습니다.
// 아래의 inputInt는 실제로는 string입니다.
var inputInt = Console.ReadLine();
Console.WriteLine(inputInt);

 

3-7. dynamic 대신 var를 사용하지 않습니다.


// dynamic은 런타임 형식 유추입니다.
// 비슷해 보이지만 성질이 전혀 다른 문법입니다.

// var은 컴파일러에서 변수의 형식을 유추합니다.
// dynamic은 object처럼 동작하고 모든 연산을 지원하는 것으로 간주됩니다.
// 런타임 에러가 발생할 소지가 있습니다.

 

3-8. for 루프의 루프 변수 형식을 결정하려면 암시적 형식을 사용합니다.


var phrase = "lalalalalalalalalalalalalalalalalalalalalalalalalalalalalala";
var manyPhrases = new StringBuilder();

// 오른쪽 할당이 명시적입니다.
for (var i = 0; i < 10000; i++)
{
    manyPhrases.Append(phrase);
}

 

3-9. foreach 루프의 경우 암시적 형식을 사용하지 않습니다.


// 오른쪽 할당이 명시적입니다.
var laugh = "acdhhhdd";

// laugh에 대한 foreach요소가 명시적이지 않습니다.
// 따라서 var을 사용하지 않습니다.
foreach (char ch in laugh)
{
    if (ch == 'h')
        Console.Write("H");
    else
        Console.Write(ch);
}

 

3-10. 일반적으로 uint(부호 없는 형식) 대신 int를 사용합니다.


// uint 형식은 일반적으로 잘 사용하지 않아 
// 다른 라이브러리와의 상호작용이 힘들 수 있습니다.
uint count = 4;

// 보편적인 int 사용을 권장합니다.
int count2 = 4;

 

3-11. 배열을 간결한 구문을 사용하여 선언할 때에는 var을 사용할 수 없습니다.


string[] vowels1 = { "a", "e", "i", "o", "u" };

 

3-12. 하지만 명시적 인스턴스화를 사용하는 경우 var을 사용할 수 있습니다.


var vowels2 = new string[] { "a", "e", "i", "o", "u" };

 

3-13. 배열 크기를 지정하는 경우 한 번에 하나씩 요소를 초기화해야 합니다.


var vowels3 = new string[5];
vowels3[0] = "a";
vowels3[1] = "e";

 

3-14. Delegate 형식을 정의하는 대신 Func<>, Action<>을 사용합니다.


// Func<> Atcion<> 예제
class ActionClass
{
    public Action<int> Action1 = x => Console.WriteLine($"x is: {x}");

    public ActionClass()
    {
        Action1(3);
    }
}

// delegate 예제
class DelegateClass
{
    public delegate void Delegate1(int x);

    public void RunThis(int x)
    {
        Console.WriteLine($"x is: {x}");
    }

    public DelegateClass()
    {
        Delegate1 run = new Delegate1(RunThis);

        run(3);
    }
}

 

3-15. try-finally Dispose 말고 using을 사용합니다.


// 아래 1번과 2번은 동일한 코드입니다.

// 1. try- finally Dispose 패턴
Font font1 = new Font("Arial", 10.0f);
try
{
    byte charset = font1.GdiCharSet;
}
finally
{
    if (font1 != null)
    {
        ((IDisposable)font1).Dispose();
    }
}

// 2. using 패턴
using (Font font2 = new Font("Arial", 10.0f))
{
    byte charset2 = font2.GdiCharSet;
}

 

3-16. &대신 &&, | 대신 ||를 사용합니다.


// 아래의 경우 & 연산은 둘 다 계산하고, &&연산은 한번만 계산합니다.
if ((divisor != 0) && (dividend / divisor > 0))
{
    Console.WriteLine("Quotient: {0}", dividend / divisor);
}

if ((divisor != 0) & (dividend / divisor > 0))
{
    Console.WriteLine("Quotient: {0}", dividend / divisor);
}

 

3-17. 간결한 new 사용


// 아래 코드는 동일한 코드입니다.
var instance1 = new ExampleClass();

ExampleClass instance2 = new();

ExampleClass instance3 = new ExampleClass();

 

// 또한 아래 코드도 동일한 코드입니다.
// 개체 이니셜라이저를 사용하면 코드 간소화가 가능합니다.
var instance5 = new ExampleClass { Name = "Desktop", ID = 37414,
    Location = "Redmond", Age = 2.3 };
    
var instance6 = new ExampleClass();
instance6.Name = "Desktop";
instance6.ID = 37414;
instance6.Location = "Redmond";
instance6.Age = 2.3;

 

3-18. 제거가 필요없는 이벤트 정의 시, 람다 식을 사용합니다.


// 1. 람다식을 사용하여 이벤트 정의
public Form2()
{
    this.Click += (s, e) =>
        {
            MessageBox.Show(
                ((MouseEventArgs)e).Location.ToString());
        };
}

// 2. 별도의 함수로 분리하여 이벤트 정의
public Form1()
{
    this.Click += new EventHandler(Form1_Click);
}

void Form1_Click(object sender, EventArgs e)
{
    MessageBox.Show(((MouseEventArgs)e).Location.ToString());
}

 

 

감사합니다.

반응형