24-03-19
내배캠에서 지원하는 C# 사전 문법 기초 깃북을 정리했다.
내일부터는 Unity 게임 개발 종합반 강의를 시작해야겠다.
제공되는 C# 사전 문법 기초 노션에는 정적 배열에 관한 정보만 있어 동적 배열의 정보도 함께 찾아보았다.
// C# - 데이터형식[] 배열명 = new 데이터형식[요소 개수];
string[] game = new string[2];
string[] character;
character = new string[3];
// C++ - 데이터형식 배열명[요소 개수];
string test[5];
// C# - ArrayList , List<T>
using System.Collections; // ArrayList
using System.Collections.Generic; // List<T>
ArrayList myList1 = new ArrayList();
myList1.Add(10);
myList1.Add(20);
int val1 = (int) myList1[1];
System.Console.WriteLine(val1); // 20 출력
List<int> myList2 = new List<int>();
myList2.Add(1);
myList2.Add(2);
int val2 = L[1];
System.Console.WriteLine(val2); // 2 출력
// C++ - 포인터명 = new 데이터형식[요소 개수];
int num = 10;
int *pA = new int[num]; // 배열을 동적으로 확보
delete[] pA; // 배열을 동적으로 해제
안에 들어가는 모든 요소들이 object 타입으로 취급된다.
ArrayList는 배열 요소를 읽어 사용할 때 object를 리턴하므로 일반적으로 원하는 타입으로 먼저 캐스팅(Casting)한 후 사용하게 된다.
어떤 타입이든 ArrayList 안에 저장할 수 있다.
int val1 = (int) myList1[1]; // object -> int 형변환
배열 요소가 T 타입인 동적 배열을 지원
List<T> 클래스는 내부적으로 배열을 가지고 있으며, 동일한 타입의 데이터만 저장
배열의 크기가 부족한 경우, 자동으로 내부 배열의 크기를 두 배로 확장
ArrayList 와 다르게 캐스팅을 할 필요가 없으며, 박싱 / 언박싱의 문제를 발생시키지 않아 성능이 좋고, 코드도 간결하다.
int val2 = myList2[1]; // 형변환 필요 없음
C# 에서 사용하는 지원하는 자료구조 클래스
Collections 의 성능 문제로 대신 사용하는 Generic Collections
배열이나 컬렉션의 각 요소를 순회하는 데 사용되는 반복문
컬렉션의 각 요소를 순회할 때 사용
읽기 전용 접근 제공
int [] arr = {1,2,3,4,5};
foreach(int number in arr)
{
Console.WrtieLine(number);
// number *=2; -> 컬렉션의 요소를 변경하려고 하면 컴파일 에러 발생
}
일반적으로 C#에서 foreach 문을 사용할 때 컬렉션의 요소를 변경할 수 없으므로, 값 변경이 필요할 때는 for 루프를 사용해야 한다.
new 로 할당된 동적 배열은 foreach 문으로 순회할 수 없음
( vector 로 할당한 동적 배열은 가능 )
읽기와 쓰기 접근 모두 가능
vector<int> v = {2,4,6,8,10};
for(int i : v) // 읽기 접근
cout << i << endl;
int arr[] = {1,2,3,4,5};
for(int& num : arr) // 쓰기 접근
num *= 2; // 컬렉션의 요소 변경 가능
C# 에서의 foreach 문은 쓰기에 대한 접근이 불가능하다고 배웠지만, 마이크로소프트 Learn 에서 foreach 문에서 ref 키워드를 통해 쓰기 접근을 하는 코드를 발견했다.
Span<int> storage = stackalloc int[10];
int num = 0;
foreach (ref int item in storage)
item = num++;
foreach (ref readonly var item in storage)
Console.Write($"{item} ");
// Output:
// 0 1 2 3 4 5 6 7 8 9
매개변수 앞에 붙여 특정 기능을 제한하거나 허용하는 키워드
기본적으로 함수에 인자를 전달할 때, call by value(값 전달)
ref 키워드를 통해 call by reference(참조 전달)
public void Func(ref int n) {...}
int a = 10;
Func(ref a);
int c;
// Func(ref c); -> 초기화 하지 않은 변수는 ref 로 넘길 수 없다.
변수를 참조 형태로 전달할 때 사용
public void Func(out int n)
{
n = 10; // 내부에서 반드시 할당되어야 함
}
int num;
Func(out n);
ref 키워드는 메서드 내에서 전달하는 변수를 변경해야할 때
out 키워드는 메서드 내에서 전달하는 변수를 초기화할 때
사용하면 될 것 같다.
변수를 참조 형태로 전달할 때 사용
public void Func(in int n) { ... }
int num = 10;
Func(num);
접근 제한자 O
public class MyClass : MonoBehavior
{
int x; // 변수 생성
int y = 10; // 선언 시 초기화
// x = 10; 변수 선언 후 초기화 X
// Debug.Log("Logic Code..."); 로직 작성 X
void func() // 함수 작성
{
Debug.Log("Logic Code..."); // 로직 작성
}
public int z; // 접근 제한자 설정
}
접근 제한자 X
void func()
{
int x; // 변수 생성
int y = 10;
if(y != 10) // 로직 생성
{
Debug.Log("y != 10");
}
}
foreach 문의 예제를 찾다가 Span<T> 와 stackalloc 를 찾아보게 되고, ref 를 공부하다가 in, out 매개변수 한정자에 대해 공부하게 되었다.
꼬리 물기식 공부법 좋은 것 같다.