<T>
형태의 키워드를 이용하여 제너릭을 선언 함<T>
대신 구체적인 자료형을 넣어 줌class 클래스명<T> { 접근지정자 T 변수명; }
클래스명<자료형> 인스턴스명 = new 클래스명<자료형>();
// 제너릭 클래스 선언 예시
class Stack<T>
{
private T[] elements;
private int top;
public Stack()
{
elements = new T[100];
top = 0;
}
public void Push(T item)
{
elements[top++] = item;
}
public T Pop()
{
return elements[--top];
}
}
// 제너릭 클래스 사용 예시
Stack<int> intStack = new Stack<int>();
intStack.Push(1);
intStack.Push(2);
intStack.Push(3);
Console.WriteLine(intStack.Pop()); // 출력 결과: 3
class Pair<T1, T2>
{
public T1 First { get; set; }
public T2 Second { get; set; }
public Pair(T1 first, T2 second)
{
First = first;
Second = second;
}
public void Display()
{
Console.WriteLine($"First: {First}, Second: {Second}");
}
}
Pair<int, string> pair1 = new Pair<int, string>(1, "One");
pair1.Display();
Pair<double, bool> pair2 = new Pair<double, bool>(3.14, true);
pair2.Display();
// 출력
First: 1, Second: One
First: 3.14, Second: True
// out 키워드 사용 예시
void Divide(int a, int b, out int quotient, out int remainder)
{
quotient = a / b;
remainder = a % b;
}
int quotient, remainder;
Divide(7, 3, out quotient, out remainder);
Console.WriteLine($"{quotient}, {remainder}"); // 출력 결과: 2, 1
// ref 키워드 사용 예시
void Swap(ref int a, ref int b)
{
int temp = a;
a = b;
b = temp;
}
int x = 1, y = 2;
Swap(ref x, ref y);
Console.WriteLine($"{x}, {y}"); // 출력 결과: 2, 1
out
ref
매개변수를 사용하면 메서드 내에서 해당 변수의 값을 직접 변경할 수 있음. 이는 예기치 않은 동작을 초래할 수 있으므로 주의가 필요ref
매개변수는 값에 대한 복사 없이 메서드 내에서 직접 접근할 수 있기 때문에 성능상 이점이 있음. 그러나 너무 많은 매개변수를 ref
로 전달하면 코드의 가독성이 떨어지고 유지보수가 어려워질 수 있음out
매개변수는 메서드 내에서 반드시 값을 할당해야 함. 따라서 out
매개변수를 전달할 때 해당 변수의 이전 값이 유지되지 않으므로 주의해야 함using System;
class Program
{
static void Main()
{
// 변수 선언만 하고 초기화하지 않음
int result;
// out 매개변수로 메서드 호출
Calculate(5, 3, out result);
Console.WriteLine($"결과: {result}"); // 출력: 결과: 8
}
static void Calculate(int a, int b, out int sum)
{
// 반드시 값을 설정해야 함
sum = a + b;
}
}
static void Example(out int value, ref int refValue)
{
value = 10; // out 매개변수는 초기화 필수
refValue += 10; // ref 매개변수는 초기화되어 있음
}
static (int sum, int product) CalculateValues(int a, int b)
{
return (a + b, a * b);
}
var (sum, product) = CalculateValues(5, 3);
Console.WriteLine($"합: {sum}, 곱: {product}");
Unity에서는 여전히 out 키워드가 특정 상황에서 유용하게 사용됨
특히 Unity는 C# 7.0 이후의 최신 기능을 점진적으로 받아들이고 있지만, Unity API 자체가 out을 사용하는 경우가 많아서 이 키워드를 접할 일이 있음
Unity에서는 여전히 많이 쓰이는 이유
호환성과 성능
Unity는 최신 C# 기능을 점진적으로 도입하지만, 여전히 기존 API와의 호환성을 유지하기 위해 out을 사용하는 경우가 많음. 특히 Unity의 네이티브 엔진 코드와의 상호작용에서 out은 효율적인 데이터 반환 방법
간결함
out을 사용하면 필요하지 않은 객체나 데이터 구조를 추가로 생성하지 않고도 값을 반환할 수 있음. 이는 메모리 할당을 줄이는 데 도움이 됨
직관적 API 설계
Unity API는 사용하기 쉽도록 설계되어 있습니다. out은 초보자도 간단히 이해할 수 있으며, 명확하게 값이 반환됨을 나타내므로 직관적임
out RaycastHit hit
: 충돌된 객체와 관련된 정보를 반환하기 위해 사용됨hit
객체를 통해 충돌 위치, 충돌된 객체, 노멀 벡터 등의 정보를 얻을 수 있음using UnityEngine;
public class RaycastExample : MonoBehaviour
{
void Update()
{
if (Input.GetMouseButtonDown(0)) // 마우스 클릭 시
{
Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
if (Physics.Raycast(ray, out RaycastHit hit, 100f))
{
Debug.Log($"Hit Object: {hit.collider.gameObject.name}");
}
}
}
}
using UnityEngine;
public class ParseExample : MonoBehaviour
{
void Start()
{
string input = "123";
if (int.TryParse(input, out int result))
{
Debug.Log($"Parsed number: {result}");
}
else
{
Debug.Log("Parsing failed.");
}
}
}
1. 기본예제
using System;
class Program
{
static void Main()
{
int number = 10; // 초기화 필수
Console.WriteLine($"Before: {number}");
// ref를 사용하여 변수 전달
ModifyValue(ref number);
Console.WriteLine($"After: {number}");
}
static void ModifyValue(ref int value)
{
value *= 2; // 원본 변수 수정
}
}
Before: 10
After: 20
2. 여러 값 수정
using System;
class Program
{
static void Main()
{
int a = 5, b = 3;
Swap(ref a, ref b);
Console.WriteLine($"After Swap: a = {a}, b = {b}");
}
static void Swap(ref int x, ref int y)
{
int temp = x;
x = y;
y = temp;
}
}
After Swap: a = 3, b = 5
3. 배열과 ref
using System;
class Program
{
static void Main()
{
int[] numbers = { 1, 2, 3 };
Console.WriteLine($"Before: {string.Join(", ", numbers)}");
ModifyArray(ref numbers);
Console.WriteLine($"After: {string.Join(", ", numbers)}");
}
static void ModifyArray(ref int[] arr)
{
arr = new int[] { 10, 20, 30 }; // 배열 자체를 새로운 것으로 변경
}
}
Before: 1, 2, 3
After: 10, 20, 30