[C#]클래스 메소드(in,out,ref)

2011. 4. 6. 10:23개발관련기록/C#

반응형

출처 : http://coolprogramming.springnote.com/pages/7059773

이번 시간은 클래스의 메소드에 대한 이야기입니다.

클래스는 크게 필드(정적인 상태를 표현)와 메소드(동적인 기능을 표현)로 구성됩니다. 대부분의 클래스와 객체에서 필드는 캡슐화되어 사용자(client)에게 감추어지기 때문에 필드보다는 메소드가 그만큼 중요한 요소가 됩니다. 또 대부분 인터페이스(서버와 클라이언트 사이의 약속과 통신)는 메소드를 사용합니다.

 

C#에서 서버와 클라이언트가 통신(메시지를 주고받기)하기 위해서는 인터페이스를 사용해야 하는데 이 인터페이스는

  • public 필드 : 캡슐화를 위배하므로 잘 사용되지 않으며 정적이므로 값만을 주고받을 수 있음.
  • public 메소드 : 대부분의 인터페이스가 이에 해당함.
  • public 속성 : C# 문법으로 제공하는 특수한 메소드 05. C# 클래스 참고.

이라 할 수 있습니다.

 1, 접근 한정자(Access Modifiers)

 우선 형식의 멤버에 지정될 수 있는 접근 한정자는 5가지입니다.

  • private : 동일한 클래스 내에서만 접근 가능합니다.(지정하지 않으면 기본으로 private)
  • public : 클라이언트 코드 어디에서도 접근 가능합니다.
  • protected : 동일한 클래스와 파생 클래스에서 접근 가능합니다.
  • internal : 동일한 어셈블리에서만 접근 가능합니다.
  • protected internal : 동일한 어셈블리와 다른 어셈블리 파생 클래스에서 접근 가능합니다.

형식에 지정될 수 있는 접근 한정자는 3가지입니다.

  • public :  클라이언트 코드 어디에서도 이 형식을 사용할 수 있습니다.
  • internal : 동일한 어셈블리에서 이 형식을 사용할 수 있습니다. (지정하지 않으면 기본으로 internal)
  • private : 중첩 형식에만 지정하여 외부 형식에서만 사용할 수 있습니다.

접근 한정자 = > http://msdn.microsoft.com/ko-kr/library/ms173121.aspx

 접근한정자.PNG

 

2, 메소드 매개변수 한정자(in, out, ref, params)

 매개변수는 변수의 사용 목적에 따라 크게 2가지로 나뉩니다.

  • 출력 매개변수(out parameter): 서버에서 클라이언트로 값을 전달할 목적으로 사용됩니다.
  • 입력 매개변수(in parameter): 클라이언트에서 서버로 값을 전달할 목적으로 사용됩니다.

 

 보통 메소드는 매개변수를 사용하여 입력을 받고 리턴을 사용하여 출력하지만 출력 매개변수를 사용해서도 출력할 수 있습니다.

아래는 리턴과 출력 매개변수를 사용한 값 출력 그림입니다.

리턴을사용한출력.PNG 

출력_매개변수를사용한출력.PNG 

 

C# 문법에서도 입력, 출력 매개변수를 구분하기 위한 키워드를 제공합니다.

  • 입력 매개변수

    • 키워드 생략(없음): 입력 매개변수로 사용됩니다.
  • 출력 매개변수

    • out : 출력 매개변수로만 사용됩니다.
    • ref : 입,출력 매개변수로 사용됩니다.

 입,출력 매개변수는 값 형식과 참조 형식이 약간 다르게 동작합니다.

 

2.1, 값 형식의 입,출력 매개변수

첫째, 입력 매개변수(키워드 없음)

  1. using System;

    namespace NetGong

    {

      class Program

      {

        static void PrintInt(int num)

        {

          Console.WriteLine(num);

        }

        static void Main(string[] args)

        {

          int n = 10;

          PrintInt(n);

        }

      }

    }

10

 num은 입력 매개변수로 num은 n의 복사본 값입니다. 그러므로 num이 혹 변경되더라도 원본 n은 전혀 변화가 없습니다.

값입력매개변수.PNG 

 

 

둘째, 출력 매개변수(out)

  1. using System;

    namespace NetGong

    {

      class Program

      {

        static void Add(int c, int d, out int sum)

        {

          sum = c + d;

        }

        static void Main(string[] args)

        {

          int a=10, b=20;

          int n;

          Add(a, b, out n);

     

          Console.WriteLine(n);

        }

      }

    }

30

 sum은  출력 매개변수(out)로 sum과 n은 같은 메모리 공간의 이름(변수)입니다. sum은 즉 n의 참조입니다. 그러므로 sum이 변경되면 n도 변경됩니다.

 값출력(out)매개변수.PNG

 

셋째, 입,출력 매개변수(ref)

  1. using System;

    namespace NetGong

    {

      class Program

      {

        static void Increment(ref int num)

        {

          num++;

        }

        static void Main(string[] args)

        {

          int n=10;

     

          Console.WriteLine(n);

          Increment(ref n);

          Console.WriteLine(n);

        }

      }

    }

10
11

입,출력 매개변수 키워드 ref는 out과 동일하게 동작합니다. 단지 다른 점은 꼭 값이 초기화되어 있어야 합니다. 입력으로도 사용하고 출력으로도 사용하기 위한 변수니까요. 만약 초기화되지 않은 변수를 ref 인수로 전달하면 에러가 발생합니다. C#은 이렇게 사용 용도에 대한 명확한 문법을 제공합니다.

값입출력(ref)매개변수.PNG 

그래서 ref 키워드는 Swap()처럼 입력 값을 매개변수로 받아 다시 출력하고자 할 때 사용합니다.

  1. using System;

    namespace NetGong

    {

      class Program

      {

        static void Swap(ref int a, ref int b)

        {

          int temp = a;

          a = b;

          b = temp;

        }

        static void Main(string[] args)

        {

          int n1 = 10, n2 = 20;

         

          Console.WriteLine("{0} {1}", n1, n2);

          Swap(ref n1, ref n2);

          Console.WriteLine("{0} {1}", n1, n2);

        }

      }

    }

10 20
20 10

결과는 간단!

 Swap입출력매개변수.PNG

 

2.2, 참조 형식의 입,출력 매개변수

 첫째, 입력 매개변수(키워드 없음)

  1. using System;

    namespace NetGong

    {

      class Point

      {

        private int x;

        public int X

        {

          get { return x; }

          set { x = value; }

        }

        private int y;

        public int Y

        {

          get { return y; }

          set { y = value; }

        }

      }

      class Program

      {

        static void PrintPoint(Point arg)

        {

          Console.WriteLine("({0}, {1})", arg.X, arg.Y);

        }

        static void Main(string[] args)

        {

          Point pt = new Point(){X=2, Y=3}; //05. 참고

          PrintPoint(pt);

        }

      }

    }

 (2, 3)

 arg는 입력 매개변수로 arg는 pt의 복사본입니다. 그러므로 arg를 혹 변경되더라도 원본 pt는 전혀 변화가 없습니다. 여기까지는 값 형식과 똑같습니다. 하지만, 참조 형식에서 주의할 점이 있습니다. arg와 pt는 같은 객체를 참조하고 있으므로 만약 arg가 가리키는 객체의 값을 변경하면 원본 객체 pt가 변경됩니다.

위 예제 메모리 그림입니다.

 참조입력매개변수.PNG

 

  1. using System;

    namespace NetGong

    {

      class Point

      {

        private int x;

        public int X

        {

          get { return x; }

          set { x = value; }

        }

        private int y;

        public int Y

        {

          get { return y; }

          set { y = value; }

        }

      }

      class Program

      {

        static void PrintPoint(Point arg)

        {

          Console.WriteLine("({0}, {1})", arg.X, arg.Y);

          arg = new Point() { X = 5, Y = 8 };

        }

        static void Main(string[] args)

        {

          Point pt = new Point() { X = 2, Y = 3 }; 

          PrintPoint(pt);

          Console.WriteLine("({0}, {1})", pt.X, pt.Y);

        }

      }

    }

 (2, 3)
(2, 3)

arg가 새로운 객체를 참조하더라도 pt는 여전히 원본 객체를 참조합니다.

위 예제 메모리 그림입니다.

참조입력매개변수2.PNG 

 

 

하지만 arg를 사용하여 객체의 상태 값을 변경하면 같은 객체를 참조하고 있으므로 pt 원본 객체의 값이 변경됩니다.

  1. using System;

    namespace NetGong

    {

      class Point

      {

        private int x;

        public int X

        {

          get { return x; }

          set { x = value; }

        }

        private int y;

        public int Y

        {

          get { return y; }

          set { y = value; }

        }

      }

      class Program

      {

        static void PrintPoint(Point arg)

        {

          Console.WriteLine("({0}, {1})", arg.X, arg.Y);

          arg.X = 5;

          arg.Y = 8;

        }

        static void Main(string[] args)

        {

          Point pt = new Point() { X = 2, Y = 3 }; //05. uÆi

     

          PrintPoint(pt);

          Console.WriteLine("({0}, {1})", pt.X, pt.Y);

        }

      }

    }

(2, 3)
(5, 8)

 arg와 pt가 같은 객체를 참조하므로 arg의 상태 값이 변경되면 pt 원본의 상태 값이 변경됩니다.

위 예제 메모리 그림입니다.

참조입력매개변수3.PNG 

 

둘째, 출력 매개변수(out)

  1. using System;

    namespace NetGong

    {

      class Point

      {

        private int x;

        public int X

        {

          get { return x; }

          set { x = value; }

        }

        private int y;

        public int Y

        {

          get { return y; }

          set { y = value; }

        }

      }

      class Program

      {

        static void CreatePoint(out Point arg)

        {

          arg = new Point() { X = 2, Y = 3 };

        }

        static void Main(string[] args)

        {

          Point pt;

     

          CreatePoint(out pt);

          Console.WriteLine("({0}, {1})", pt.X, pt.Y);

        }

      }

    }

(2, 3)

 위 예제의 메모리 그림입니다.

참조출력매개변수.PNG 

 

셋째, 출력 매개변수(ref)

값 형식처럼 미리 초기화 후 출력 매개변수로 사용되어야 한다는 것입니다. 나머지는 out과 같습니다.

 

2.3,  params 매개변수 한정자

 params는 C나 C++의 가변 인자처럼 동작합니다. 하지만 더 강력한 기능을 제공합니다.

params 한정자는 배열을 사용하므로 배열을 공부한 후...

 

.....

 

마지막으로 인터페이스로 사용되는 속성은 05. C# 클래스를 참고하세요.

 

~~ 

=======================================================================================
출처 : http://coolprogramming.springnote.com/pages/7059773

반응형