전체 페이지뷰

2016년 12월 14일 수요일

C# Method

아직 데이터형 중 배열과 컬렉션에 대해서는 알아보지 않았지만, 그에 앞서 메소드(method, C에서는 함수라 불러왔던)에 대해서 공부하겠습니다. 컬렉션에는 인터페이스라는 개념이 들어가므로 선행 지식이 필요하다 생각되므로 좀 뒤에서 알아보기로 합니다.


이미 다들 알고 계시겠지만 특정 행위를 수행하는 코드를 하나로 묶어놓은 것을 메소드라 합니다. 그래서 그 행위가 필요할 때 그 메소드를 호출하기만 하면 다시 작성할 필요가 없습니다.


class 클래스이름
{
    한정자 반환형식 메소드명(매개변수)
    {
        코드;
        return 반환형식에 일치하는 결과;
    }
}

의 구조를 갖습니다. 실제 예는 다음과 같습니다.
class Calculator
{
    public static int Plus(int a, int b)
    {
        Console.WriteLine("Input : {0} {1}", a, b);
        int result = a + b;
        return result;
    }
}
cs

여기서는 접근한정자로 public static이 쓰였습니다. static은 메소드가 클래스의 인스턴스가 아닌 클래스 자체에 속하도록 하는 한정자로서 인스턴스를 만들지 않고도 메소드를 사용할수 있도록 만듭니다. 앞으로 클래스를 공부할 때 자세히 알아보도록 하고 여러가지 형태를 구경만 해보고 넘어가겠습니다.

    abstract class Motorcycle
    {
        // Anyone can call this.
        public void StartEngine() {/* 코드; */ }
        // Only derived classes can call this.
        protected void AddGas(int gallons) { /* 코드; */ }
        // Derived classes can override the base class implementation.
        public virtual int Drive(int miles, int speed) { /* 코드; */ return 1; }
        // Derived classes must implement this.
        public abstract double GetTopSpeed(); 
    }
cs

return은 일종의 점프문으로서 메소드에서 호출되면 결과값을 반환하고 메소드 코드블럭을 빠져나오도록 합니다. 반환형이 없는 void의 경우에도 return;문으로 메소드를 종결할 수 있습니다.

매개변수

우리가 어떤 메소드에 매개변수를 주어 작업을 수행했다고 해 봅시다.
Method(x,y)   처럼 말이죠. 
Method에 우리는 x, y 두 변수를 대입해서 작업을 했지만 실제로는 x, y를 넘겨주는 것이 아니며 값을 복사해서 넘겨주게 되므로 원래의 x, y에는 아무런 영향이 없습니다.
이런 방식을 "Call by value"라고 부릅니다.

using System;
class Program
{
    public static void SwapCallByValue(int a, int b)
    {
        int temp = b;
        b = a;
        a = temp;
    }
    static void Main(string[] args)
    {
        int x = 3, y = 4;
        Console.WriteLine("x:{0}, y:{1}", x, y);
        SwapCallByValue(x, y);
        Console.WriteLine("x:{0}, y:{1}", x, y);
    }
}
cs
SwapCallByValue라는 메소드를 작성했습니다. 정수 a,b를 받아서 내부적으로 값을 서로 바꿔주는 메소드입니다. 이 프로그램의 실행결과는 어떨까요?
결과)
x:3, y:4
x:3, y:4
x, y 값이 서로 바뀌지 않고 원래 그대로입니다.

그럼 매개변수로 주어진 변수에 직접 접근(Call By Reference)하려면 어떻게 할까요? C 언어에서 우린 포인터를 넘겨주어 저장된 주소에 직접 접근토록 했습니다. C#에서는 매개변수 앞에 "ref"키워드를 넘겨주면 간단히 해결됩니다(메소드 호출시에도 ref를 붙여줍니다).

using System;
class Program
{
    public static void SwapCallByValue(ref int a, ref int b)
    {
        int temp = b;
        b = a;
        a = temp;
    }
    static void Main(string[] args)
    {
        int x = 3, y = 4;
        Console.WriteLine("x:{0}, y:{1}", x, y);
        SwapCallByValue(ref x, ref y);
        Console.WriteLine("x:{0}, y:{1}", x, y);
    }
}
cs

"ref"와 비슷한 것으로 "out" 키워드가 사용 가능합니다. ref의 경우에는 미리 그 변수가 초기화 되어야 하지만 out은 초기화 없는 변수 선언만으로 가능하고 메소드의 결과로서 그 변수에 반드시 그 변수에 값이 할당되어야 합니다(그렇지 않으면 에러가 납니다).

주로 메서드가 한개의 return값이 아닌 여러개의 값을 반환하도록 하는데 유용합니다.

out 키워드의 예를 들어 보겠습니다.
using System;
class Program
{
    static void Calc(int a,int b,out int mul, out int add)
    {
        mul = a * b;
        add = a + b;
        
    }
    static void Main()
    {
        int a = 10;
        int b = 5;
        int c, d;
        Calc(a, b, out c, out d);
        Console.WriteLine("a={0}, b={1}, a*b={2}, a+b={3}", a, b, c, d);
    }
}
cs

결과) a=10, b=5, a*b=50, a+b=15

메소드 오버로딩

오버로딩이란 같은 함수명으로 매개변수가 다른 여러개의 함수를 정의할 수 있는 방법입니다. 오버로딩이 없었다면 라이브러리에 참고해야할 함수가 몇십배 늘어났을 겁니다. 우리가 여태 가장 많이 쓴 WriteLine()만 해도 사실 매개변수가 다른 19개 메소드의 집합입니다.

가변길이 매개변수

"params" 키워드를 사용해서 여러개의 매개변수를 처리할 수 있습니다.

public static void UseParams(params int[] list)
{
    for (int i = 0; i < list.Length; i++)
    {
        Console.Write(list[i] + " ");
    }
    Console.WriteLine();
}
cs

정수 변수의 list를 받아 출력하는 메소드입니다.
UseParams(1, 2, 3, 4);
UseParams(1, 2, 3, 4, 5);
처럼 사용 가능합니다.

명명된 매개변수

Named parameter는 코드의 가독성을 높이기 위한 장치입니다. 매개변수가 많을 때 혼동이 되지 않도록 도와줍니다.
static int CalculateBMI(int weight, int height)
{
    return (weight * 703/ (height * height);
}
cs
신체발달지수를 계산해주는 위와 같은 메소드를 생각해 봅시다.

여태까지 우리는 위의 함수를 호출할 때
CalculateBMI(123, 64)
와 같이 사용 했습니다. 그런데 순서가 기억나지 않는다던가 할때,

CalculateBMI(weight: 123, height: 64)
의 형태로 이름을 붙여줄 수 있습니다. 

CalculateBMI(height: 64, weight: 123)
처럼 순서를 바꿔서도 가능하며,

CalculateBMI(123, height: 64)
처럼 하나에만 이름을 붙일 수도 있는데 이럴 경우 앞의 것만 생략가능하며 순서를 지켜야 합니다..

CalculateBMI(weight: 123, 64)
CalculateBMI(height: 64, 123)
에러를 발생시킵니다.

선택적 매개변수

메소드의 매개변수는 기본값을 지정할 수 있습니다. 기본값을 가질 경우 메소드를 호출 시 인자를 생략할 수 있으므로 선택적 매개변수(optional parameter)라고 부르며, 항상 반드시 값을 입력해야 하는 기본값이 없는 필수매개변수 뒤에 와야 합니다. 또한, 생략이 가능하여 입력한 인자가 무엇인지 혼동될 수 있으므로 명명된 매개 변수와 같이 사용하여 혼동을 줄일 수 있습니다.
using System;
class Program
{
    static void Calc(string name, int weight ,int height=170)
    {
        Console.WriteLine("{0}, {1}, {2}", name, weight, height);
    }
    static void Main(string[] args)
    {
        Calc("Adam"67180);
        Calc("Bob"55);
        Calc(name: "Charles", weight: 78);
    }
}
cs


결과)
Adam, 67, 180
Bob, 55, 170
Charles, 78, 170

댓글 없음:

댓글 쓰기