Language/C#

[C#] 기본 문법 및 C++과 비교시 차이

마탁이 2020. 12. 17. 16:18

1. Main 코드 (가장 기초적으로 만들어지는 코드 전문)

  - 개인적으로는 Java를 먼저 배우고 C#을 배우는 입장으로서 Java와 매우 유사하다고 생각한다.

  - #include -> using

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace ConsoleApp1
{
    class Program
    {
        static void Main(string[] args)
        {
        	Console.WriteLine("Hello World!");   
        }
    }
}

 

2. Console.WriteLine()

  - printf()와 std::cout 를 섞어놓은 출력 방식이라고 느꼈음.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace ConsoleApp1
{
    class Program
    {
        static void Main(string[] args)
        {
        	int a = 12345;

            Console.WriteLine("|{0,15}|", a);
            Console.WriteLine("|{0,-15}|", a);
            Console.WriteLine("|{0,15:N0}|", a);
            Console.WriteLine("|{0,-15:N0}|", a);
        }
    }
}

<위 코드 출력 결과>

 

3. Console.ReadLine()

  - scanf() 혹은 std::cin 의 기능

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace ConsoleApp1
{
    class Program
    {
        static void Main(string[] args)
        {
        	Console.WriteLine("수를 입력하세요 : ");
        	string line = Console.ReadLine();
            Console.WriteLine("출력 : " + line);
        }
    }
}

 

4. string to int 변환

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace ConsoleApp1
{
    class Program
    {
        static void Main(string[] args)
        {
        	string str = "123";
            int integer = int.Parse(str);

            Console.WriteLine(integer);
        }
    }
}

 

5. Call By Value & Call By Reference

  - 포인터(*), 주소 참조(&)의 선언 개념없이 ref 로 주소 전달을 할 수 있는 것으로 보인다.

  - class 함수 내의 메소드들은 static을 추가.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace ConsoleApp1
{
    class Program
    {
		static void testSwap(int a, int b)
        {
            int temp = b;
            b = a;
            a = temp;
        }

        static void testSwap(ref int a, ref int b)
        {
            int temp = b;
            b = a;
            a = temp;
        }
    
        static void Main(string[] args)
        {
			int num1 = 10;
            int num2 = 20;
            
            Console.WriteLine("before {0}, {1}", num1, num2);
            testSwap(num1, num2);
            Console.WriteLine("after {0}, {1}", num1, num2);
            
            Console.WriteLine("using ref");
            
            testSwap(ref num1, ref num2);
            Console.WriteLine("after {0}, {1}", num1, num2);
        }
    }
}

 

6. 배열을 전달하는 방법 (parmas)

  - 매개변수에 'params' 키워드를 붙여 배열을 편하게 전달할 수 있다.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace ConsoleApp1
{
    class Program
    {
        static void testParams(params int[] list)
        {
            Console.WriteLine("list Size : " + list.Length);
            foreach(int data in list)
            {
                Console.Write(data + " ");
            }
        }
    
        static void Main(string[] args)
        {
            Console.WriteLine("Params Test");
            testParams(10, 20, 30, 40, 50, 60, 70);
        }
    }
}

 

7. System.Arrays

  - 차수, Clear 등 배열을 다루기 위한 방법을 제공.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace ConsoleApp1
{
    class Program
    {   
        static void Main(string[] args)
        {
            Console.WriteLine("System.Arrays Test");

            int[] reading = new int[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
            // Rank
            Console.WriteLine("Rank" + reading.Rank);

            // Clear
            Console.WriteLine("Clear !");
            Array.Clear(reading, 0, 5);

            // ForEach
            Array.ForEach<int>(reading, new Action<int>(ShowValue));
        }
    }
}

 

8. 다차원 배열 선언

  - C#에서도 역시 다차원 배열을 선언할 수 있으나 선언 방법이 가장 새롭다(?) 라고 생각했다.

int[,] multiReading = new int[1, 2];

 

9. 접근 제한자(internal, protected internal)

 - internal

   > 동일한 어셈블리의 코드에서는 형식이나 멤버에 액세스 할 수 있지만

      다른 어셈블리의 코드에서는 액세스 할 수 없다. (프로젝트 내에서만 접근 가능)

   > Helper Class를 만드는데 주로 사용.

 - protected internal

   > 형식 또는 멤버가 선언된 어셈블리의 모든 코드에서 또는 다른 어셈블리의 파생 class 내에서

      형식 또는 멤버에 액세스 할 수 있다.

   > 어셈블리 내의 상속 클래스에서만 접근 가능.

 * 어셈블리

   > 한 프로젝트가 반환하는 결과물. (.exe or .dll)

 

10. 클래스 상속 중 sealed

- 클래스명 앞에 'sealed' 키워드를 사용하면 해당 클래스는 상속 할 수 없다. (부모 클래스로 사용하지 못 함)

 

11. 클래스 멤버 변수에 대한 get / set

  - 정보 은닉을 위한 getter 과 setter 를 키워드로 제공.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace ConsoleApp1
{
    public class MyClass
    {
        private string name;

        public string Name
        {
            get
            {
                return name;
            }
            set
            {
                name = value;
            }
        }
    }

    class Program
    {
        static void Main(string[] args)
        {
            MyClass mc = new MyClass();

            Console.WriteLine("mc name : " + mc.Name);
            mc.Name = "matagi";
            Console.WriteLine("mc name : " + mc.Name);
        }
    }
}

- 위 get과 set을 C# 3.0 이후 부터 아래와 같이 축약하여 사용할 수 있다.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace ConsoleApp1
{
    public class MyClass
    {
        public string Name { get; set; } = "empty";   
    }

    class Program
    {
        static void Main(string[] args)
        {
            MyClass mc = new MyClass();

            Console.WriteLine("mc name : " + mc.Name);
            mc.Name = "matagi";
            Console.WriteLine("mc name : " + mc.Name);
        }
    }
}

 

 

12. 확장 메소드

  - 이미 빌드된 라이브러리를 참조해 사용 중이며 이 라이브러리의 기존 클래스 기능을 좀 더 확장 시키고 싶을 때 사용.

    하지만 라이브러리의 소스 코드가 없기 때문에 클래스를 직접 수정 불가능 할 때 사용.

  - 상속도 하나의 방법이 될 수 있지만, 클래스가 sealed로 한정되어 있는 경우 확장 메소드의 사용을 고려할 수 있다.

using System;
using Extenstion;

namespace Extenstion
{
    public static class ExtensionMethod
    {
        public static int Multiplication(this int var, int a, int b)
        {
            int result = var;

            for (int i = a; i <= b; i++)
                result += i;

            return result;
        }
    }

    namespace Example
    {
        class Program
        {
            static void Main(string[] args)
            {
                Console.WriteLine("{0}", 5.Multiplication(2, 3));
            }
        }
    }
}

 

13. 분할 클래스(Partical Class)

  - 클래스의 구현이 길어질 경우 두 개 이상의 소스 파일로 분할하여 동시에 작업을 수행하거나,

    관리의 편의를 위해 클래스를 분할하기도 한다.

  - 클래스를 분할할려면 'partical' 키워드를 사용한다.

using System;
namespace Example
{
    partial class Nested
    {
        public void Test() { Console.WriteLine("Test()"); }
    }
    
    partial class Nested
    {
        public void Test2() { Console.WriteLine("Test2()"); }
    }
    
    partial class Nested
    {
        public void Test3() { Console.WriteLine("Test3()"); }
    }
    
    class Program
    {
        static void Main(string[] args)
        {
            Nested nested = new Nested();
            nested.Test();
            nested.Test2();
            nested.Test3();
        }
    }
}

 

14. 중첩 클래스(Nested Class)

  - 클래스 내에 또 클래스가 정의 된 것.

  - 내부에 쓰인 클래스는 접근 지정자가 명시되어 있지 않으면 'private'로 지정된다.

 

15. NULL 조건 연산자

   - 조건문을 통한 null 조건 검사가 아닌 연산자를 이용해 편리함을 증대시킴.

   - ?.

    > 멤버에 접근하기 전 체크

   - ?[]

    > 인데스 작업을 수행하기 전에 체크

using System;
namespace Example
{
    class Program
    {
        static void Main(string[] args)
        {
            string result = "string";

            if(result != null)
            {
                // to do
            }
        }
    }
}

  - 위와 같은 코드를 아래 처럼 작성할 수 있다.

using System;
namespace Example
{
    class Program
    {
        static void Main(string[] args)
        {
            string result = "string";

            result?.Substring(0, 2);
        }
    }
}

  - 만약 null이라면 '?' 연산자 뒤의 내용은 실행하지 않고 다음 문장으로 넘어간다.

 

16. 문자열 보간

  - 기존에는 String.Format()과 같은 메서드를 사용하여 형식화된 문자열을 출력할 수 있었으나,

    문자열 보간을 사용하면 기존의 방법보다 더 읽기 쉽고 편리하게 형식화된 문자열을 만들 수 있다.

string name = "마크";
var date = DateTime.Now;

// 복합 형식 지정(Composite formatting):
Console.WriteLine("안녕, {0}! 오늘은 {1}, {2:HH:mm}이야.", name, date.DayOfWeek, date);

// 문자열 보간(String interpolation):
Console.WriteLine($"안녕, {name}! 오늘은 {date.DayOfWeek}, {date:HH:mm}이야.");

 

17. 인덱스 초기자

  - Dictionary 객체를 인덱스를 통해 초기화 할 수 있다.

private Dictionary webErrors = new Dictionary
{
	[404] = "Page not Found",
	[302] = "Page moved, but left a forwarding address.",
	[500] = "The web server can't come out to play today."
};

 

18. nameof 연산자

  - 변수나 자료형, 멤버의 이름에 해당하는 문자열을 가져오는 데 사용한다.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace ConsoleApp1
{
    class Program
    {
        static void Main(string[] args)
        {
            var localTime = DateTime.Now.ToLocalTime();
            Console.WriteLine(nameof(localTime)); // "localTime"
            Console.WriteLine(nameof(args)); // "args"
            Console.WriteLine(nameof(System.IO)); // "IO"
            Console.WriteLine(nameof(Main)); // "Main"
            Console.WriteLine(nameof(Program)); // "Program"
        }
    }
}

 

19. catch/finally 에서 await 사용try
  - 비동기적으로 예외를 기록하거나, 마지막으로 자원을 해제하는 등의 작업에서 유용하게 사용될 수 있다.

try
{
    await OperationThatMayThrowAsync();
}
catch (ExpectedException ex)
{
    await MyLogger.LogAsync(ex);
}

 

20. out 변수

  - 'out' 키워드를 사용하면 참조를 통해 인수를 전달할 수 있다. (초기화할 필요 없다)

    (ref의 경우에는 변수를 전달하기 전 초기화 해야한다. 즉, 호출하는 측에서 반드시 값을 할당해야 한다.)

  - out과 ref는 모두 Call By Reference를 위한 키워드 이다.

    차이점은 아래와 같다.

     1) out으로 지정된 지정된 인자에 넘길 변수는 초기화하지 않아도 된다.

        (초기화해도 out 인자를 받는 메서드에서 그 값을 사용할 수 없음)

     2) out으로 지정된 인자를 받는 메서드는 반드시 변수에 값을 넣어서 반환해야 한다.

using System;


namespace ConsoleApp
{
    class Program
    { 
        public static void SumAndSub(ref int a, out int sub, int amount)
        {
            sub = a - amount;
            a += amount;
        }
        
        static void Main(string[] args)
        {
            int a = 30;
            SumAndSub(ref a, out int sub, 4);

            Console.WriteLine("a : " + a + " sub : " + sub);
        }
    }
}

 

21. TryParse

  - 각 기본 타입에 TryParse라는 메서드를 제공하는데, 이 메서드는 변환이 성공했는지 여부를 true/false로 반환하고

    성공하면 out을 지정된 result 변수에 값을 반환한다.

using System;


namespace ConsoleApp
{
    class Program
    {         
        static void Main(string[] args)
        {
            string str = "1234";

            if (int.TryParse(str, out int a))
            {
                // TryParse(str, out _) : 변환 값이 필요 없을 경우
                Console.WriteLine("string to int 변환 성공 : " + a);
            }
            else
            {
                Console.WriteLine("ERROR !");
            }
        }
    }
}

'Language > C#' 카테고리의 다른 글

[C#] 박싱(Boxing)과 언박싱(Unboxing)  (0) 2020.12.23
[C#] const 와 readonly  (0) 2020.12.23
[C#, 공통] 변수 및 함수 표기 방식  (0) 2020.12.23
[C#] struct, class의 참조 형식  (0) 2020.12.23
[C#] 튜플의 사용  (0) 2020.12.17