본문 바로가기

C#/이것이 C#이다

6장. 확장메소드, this와 ref, out, params 등 키워드, string.Empty

반응형

메소드


메소드 기본 형식

class Program {
	static void Main()
    {
    	Console.WriteLine(Plus(1, 2));
    }
    public static int Plus(int a, int b) {
    	return a + b;
    }
}

 

this 키워드

아래의 코드에서 B의 name 변수와 C의 name 변수를 어떻게 구분할 것인가?

그래서 등장한 것이 this 키워드이다.

class A {
	abstract string name;
}

B = new A() {
	string name = "나는 B";
};

C = new A() {
	string name = "나는 C";
};

void setName(name) { } //어떻게 구분하지?
class A {
	abstract string name;
}

B = new A() {
	string name = "나는 B";
};

C = new A() {
	string name = "나는 C";
};

void getName(this string name) {
	Console.WriteLine(name);
}
B.getName(); //나는 B
C.getName(); //나는 C
되도록 this 키워드를 사용하는 것이 바람직하다.
이유는... 예상치 못한 값을 매개변수로 가져오는 것을 방지할 수 있으니까?
정확하지 않은 문법이니 참고용으로만 봐주세요.

 

참조에 의한 매개 변수 전달, ref

ref: 매개변수로 전달한 값의 원본(참조를 반환함)이 변경되는것

static void Main() {
	int a = 1; b = 2;
    Console.WriteLine($"a:{a} b:{b}");
    Swap(ref a, ref b);
    Console.WriteLine($"a:{a} b:{b}");
}

static void Swap(ref int a, ref int b) {
	int temp = b; b = a; a = temp;
}
price = 100;
ref int localPrice = ref getPrice(); //localPrice = price = 100
int normalPrice = getPrice(); //normalPrice = 100
localPrice = 200; //price = 200, localPrice = 200, normalPrice = 100

getPrice() {
	return ref price;
}

 

결과값을 반환받는, out

Divide(20, 3, out int qoutient, out int remainder);

static void Divide(int a, int b, out int qoutient, out int remainder)
{
	qoutient = a / b; // 몫
    remainder = a % b; // 나머지
}

 

다양한 길이의 배열을 매개변수로 받을 수 있는, params

static int Sum(int[5] args);
static int Sum(int[] args); // 오류 - 인수 []개를 사용하는 Sum 메소드에 대한 오버로드가 없습니다.
메소드 오버로딩: 같은 메소드명의, 매개변수 개수와 형식이 다른, 다른 함수를 만드는 것

 

명명된 매개변수

PrintUser(married: true, name: "john", age: 30);
static void PritUser(string name, int age, bool married);

 

선택된 매개변수

PrintUser("john", 30);
static void PritUser(string name, int age, bool married = false);
married = false 처럼 기본값을 설정하면, 선택적 매개변수를 사용할 수 있다.

 

로컬 함수: 클래스의 멤버가 아닌 메소드 안에서 선언된 함수

 


 

확장메소드 실습

클래스 라이브러리(.NET Framework)로 새 프로젝트를 생성한다.

이 라이브러리는 독자적으로 실행할 수 없는 프로젝트이다.

 

같은 솔루션 내에 콘솔 앱(.Net Framework) 프로젝트를 오른쪽클릭하여 시작 프로젝트로 설정한다.

새항목-클래스(.cs)파일을 생성한다.

 

생성한 라이브러리를 참조 가능하게 만들기 위해,

Application의 참조 클릭, 참조 추가-프로젝트-CoreBase.Library를 선택한다.

이때 라이브러리의 클래스 파일의 네임스페이스를 모두 CoreBase,Library로 설정한다.

 

Visual Studio 2019, 글꼴 변경: 도구-옵션-환경-글꼴 및 색-글꼴 => 프로그램 종료 후 다시 켜기

1. ConditionExtentions

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

namespace CoreBase.Library // namespace 변경
{
    public static class ConditionExtentions
    {
        public static int vIndexOf(this string source, char value) // indexOf를 확장하는 함수
        {
            if (source == null) // 예외처리
            { return 0; }
            return source.IndexOf(value);
        }

        #region [Bool Type]
        public static bool vIsNull(this bool? source)
        { return source == null ? true : false; }

        public static bool vIsEmpty(this bool? source) //bool은 null값과 빈값이 구분되지 않음
        { return source.vIsNull(); }

        public static bool vIsNotEmpty(this bool? source)
        { return !source.vIsEmpty(); }

        public static bool vIsDefault(this bool? source)
        {
            var defaultBool = default(bool);
            return source == defaultBool ? true : false;
        }
        #endregion


        #region [String Type]
        public static bool vIsNull(this string source)
        { return source == null ? true : false; }

        public static bool vIsEmpty(this string source) //string은 null값과 빈값이 구분됨
        { return source == "" ? true : false; }

        public static bool vIsNotEmpty(this string source)
        { return !source.vIsEmpty(); }

        public static bool vIsDefault(this string source)
        {
            var defaultString = default(string);
            return source == defaultString ? true : false;
        }
        #endregion


        #region [Int Type]
        // 생략
        #endregion
    }
}
함수 자체를 return할 수도 있다!

 

2. SafeValueExtentions

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

namespace CoreBase.Library
{
    public static class SafeValueExtentions
    {
        #region [String Type]
        public static string vSafe(this string source)
        {
            return source ?? string.Empty; //string.Empty == "" (다만 객체를 생성하지 않음)
        }

        public static string vSafe(this string source, string defaultValue)
        {
            return source ?? defaultValue;
        }
        #endregion
    }
}

 

SafeValueExtentions.cs에서 string만 구현한 이유

 

2-1) vSafe(this string source) 함수에 대하여

bool이나 int 형에서 빈 값(Empty)은 null과 동일하기 때문입니다.

다만 string의 빈 값(Empty)는 ""로 구분이 가능합니다.

 

Console.Write로 출력해보았을 때,

null과  String.Empty(""과 동일)는 구분되지 않기 때문에

string 형만 따로 매개변수인 source가 null일 경우 String.Empty(""과 동일)로 변환해주는 함수를 만들어주었다고 생각합니다.

 

2-2) vSafe(this string source, string defaultValue) 함수에 대하여

default(bool), bool 형의 기본값은 false,

default(int), int 형의 기본값은 0이지만,

default(string), string 형의 기본값은 null입니다.

 

마찬가지로 Console.Write로 출력해보았을 때,

null과  String.Empty(""과 동일 - 내부적으로는 다르지만)는 구분되지 않기 때문에

string 형만 따로 기본값을 설정할 수 있는 함수를 만들어주었다고 생각합니다.

반응형