🧑🏻💻 2. C# 값타입 Call By Reference
함수의 Output은 꼭 Return으로 받지 않아도 된다. 바로 "Call By Reference"
-
C 포인터를 처음 배우게 되면 함수의 인자를 포인터로 보내는 방식을 기억할 것이다.
-
나아가서 C++에선
&
참조 연산자로Not Nullable
레퍼런스 접근이 가능했다. -
어쨌든 핵심은
Swap(a, b)
를 구현할 때, Call By Reference 를 사용하고
리턴이 없는 함수라도, 인풋이 되고 아웃풋이 가능하게 만드는 테크닉으로 사용 가능하다.// Call By Value : 인자는 외부에서 받아온 녀석이랑 다른녀석이다. // 다시 말하면 외부 값의 원본이 아닌 복사본이 들어 와서.. 이 스왑은 작동되지 않는다. void Swap(int a, int b) { int temp = b; b = a; a = b; }
// Call By Reference : 외부의 원본 주소를 가져온다 // 이 스왑은 실제 외부의 값이 바뀌게 된다. // 즉 이 함수를 지나기 "전"과 "후" 는 다르다는 것! void Swap(int& a, int& b) { int temp = b; b = a; a = b; }
Java는 지원 안하는 C#만의 특권! 을 누려 보자.
- Java는 Value to Call By Reference를 지원하지 않는다.
- 무조건 값타입을 멤버로 담는 클래스를 사용해야 한다 -> 억지로 Heap에 할당해야한다.
- 하지만! C#은 이러한 솔루션을 제공하고 심지어 C++ 보다 더 뛰어난 키워드를 제공한다.
- 함수내에서 인수를 전달하는데 값 형식 참조로 전달되는 인수 키워드
ref
,out
,in
씨리즈르 말해보겠따.
📄 1. 키워드
1). ref T value
초기화 여부 : 전달 되기전 초기화 필요하다
① C++ 에서 다음과 동치다.
template <typename T>
void ModifiySometing(T& value) {
...
}
② C# 에서 사용하면 다음과 같다.
static void Main(string[] args)
{
string str1 = "initString";
Console.WriteLine("SetValueRef 메소드 호출 전: {0}", str1);
SetValueRef(ref str1);
Console.WriteLine("SetValueRef 메소드 호출 후: {0}\n", str1);
}
static void SetValueRef(ref string str) {
str = "refString";
}
결과는 다음과 같다.
> SetValueRef 메소드 호출 전: initString
SetValueRef 메소드 호출 후: refString
2). out T value
초기화 여부 : 전달 되기전 초기화 필요 없다 진짜로 리턴값 같음
다만, 내부에 out
될 변수를 만들어 줘야한다
① C++ 에서 다음과 동치다.
template <typename T>
bool TrySometing(T* result) {
...
return true;
}
② C# 에서 사용하면 다음과 같다.
public class Program
{
static bool TryGetSomeString(out string str) {
str = "somestring";
return true;
}
public static void Main(string[] args) {
if(!TryGetSomeString(out string res1)) {
Console.WriteLine($"비어 있는 문자열 출력 : {res1}");
}
}
}
3). in T value
초기화 여부 : 전달 되기전 초기화를 해줘야 한다.
ref
랑 다른점은 value를 readonly
하게 받아올 수 있다는것이다
즉 함수 내부에서 in
값을 수정하지 않음으로 안전한 개발이 가능하다.
① C++ 에서 다음과 동치다.
template <typename T>
void PrintArray(const T& result) {
for(const auto& E : result) {
cout << E;
} cout << '\n';
}
② C# 에서 사용하면 다음과 같다.
public class Program
{
public ref struct Person {
public ReadOnlySpan<char> name;
public int age;
}
static void PrintStackAllocString(in ReadOnlySpan<char> sstr) {
foreach(var C in sstr) { Console.Write(C); }
}
static void PrintPersonInfo(in Person info) {
PrintStackAllocString(in info.name); Console.Write("의 나이 : ");
Console.WriteLine(info.age);
}
public static void Main(string[] args) {
Person p1;
p1.name = ['D', 'o', 'g', 'G', 'u', 'y', 'M', 'a', 'n'];
p1.age = 1234;
PrintPersonInfo(in p1);
}
}
참조
'Language > C#' 카테고리의 다른 글
| 니앙팽이 - C# | 1 | 메모리 [ Stack&Heap / Value&Reference Type / Struct&Class / Boxing&UnBoxing / Garbage Collector ] (0) | 2024.01.18 |
---|---|
| 니앙팽이 - 이벤트(C#) | 5 | UnityEvent (0) | 2023.04.14 |
| 니앙팽이 - 이벤트(C#) | 4 | Eventhandler & Event & EventArgs (0) | 2023.02.09 |
| 니앙팽이 - 이벤트(C#) | 3 | 델리게이트 액션 (Action) (0) | 2023.02.03 |
| 니앙팽이 - 이벤트(C#) | 2 | 델리게이트(Delegate) (0) | 2023.02.03 |