Media Log


1. 확장 메소드(Extension Method)


확장 메소드는 지금까지 우리가 보아왔던 메소드와는 다르게 조금 독특한 메소드라고 할 수 있습니다. 이 확장 메소드는, 기존 클래스의 기능을 확장시켜주는 메소드라고 볼 수 있습니다. 아래는 확장 메소드의 선언 형식입니다.

namespace 네임스페이스명
{
    public static class 클래스명
    {
        public static 반환형식 메소드명(this 확장대상형식 식별자, 매개변수..)
        {
            ..
        }
        ..
    }
}

선언 형식을 보시면, 정적(static) 클래스를 먼저 정의하고 그 안에 확장 메소드가 정의되었습니다. 확장 메소드 역시 정적(static) 메소드여야 합니다(정적 메소드는 객체를 만들지 않고도 바로 호출이 가능). 그리고 메소드의 첫번째 매개변수에서 this 한정자가 존재해야 합니다. 바로 확장 메소드와 관련된 예제를 살펴보도록 합시다. 

using System;
using Extension;

namespace Extension
{
    public static class ExtensionMethod
    {
        public static int Multiplication(this int var, int a, int b)
        {
            int result = var;

            for (int i = 0; i < b; i++)
                result *= a;

            return result;
        }
    }
}

namespace Example
{
    class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine("{0}", 5.Multiplication(2, 3));
        }
    }
}

결과:

40

계속하려면 아무 키나 누르십시오 . . .


코드를 보시면, 6행에서 확장 메소드인 Multiplication()을 포함하는 정적 클래스인 ExtensionMethod가 보입니다. 이 메소드가 어떻게 사용되는지는 22행을 보면 알 수 있습니다. 마치 인스턴스 메소드처럼 5의 뒤에 .을 붙여 메소드를 호출하고 있습니다. 여기서 5는 Multiplication()의 매개변수 var에 들어가며, 2는 a에, 3은 b에 들어가게 됩니다. 10~15행을 살펴보면 result란 변수에 var의 값을 담아, result에 a를 b번 곱하고 이 결과값을 호출부로 반환하여, 반환된 값을 출력시킵니다.


이러한 확장 메소드는 아래와 같은 상황에서 유용하게 쓰일 수 있습니다.

이미 빌드된 라이브러리를 참조해서 사용하고 있는데, 이 라이브러리 내부에 있는 기존의 클래스를 좀 더 확장시키고 싶어. 그런데 나에게는 이 라이브러리의 소스 코드가 없기 때문에 클래스를 직접 수정할 수는 없을 것 같아.

이 경우에는 확장 메소드를 통해 기존 클래스의 소스 코드를 변경하지 않고 기능을 확장할 수 있습니다. 물론, 이와 같은 경우에도 우리가 앞에서 배운 상속을 통해서도 기능을 확장할 수 있습니다. 상속도 좋은 방법이지만, 클래스가 sealed로 한정되어 있는 경우에는 확장 메소드의 사용을 고려해 볼 수 있습니다.


2. 분할 클래스(Partial Class)


클래스의 구현이 길어질 경우 두 개 이상의 소스 파일로 분할하여 동시에 작업을 수행하거나, 관리의 편의를 위해 클래스를 분할하기도 합니다. 클래스를 분할하려면 partial 키워드를 사용하면 됩니다. 클래스 말고도 앞으로 배울 인터페이스, 구조체에도 partial 키워드를 사용할 수 있습니다. 아래는 분할 클래스의 예제입니다.

using System;

namespace Example
{
    partial class Nested
    {
        public void Test() { Console.WriteLine("Test()"); }
    }
    partial class Nested
    {
        public void Test2() { Console.WriteLine("Test2()"); }
    }
    partial class Nested
    {
        public void Test3() { Console.WriteLine("Test3()"); }
    }
    class Program
    {
        static void Main(string[] args)
        {
            Nested nested = new Nested();
            nested.Test();
            nested.Test2();
            nested.Test3();
        }
    }
}

결과:

Test()

Test2()

Test3()

계속하려면 아무 키나 누르십시오 . . .


partial 키워드가 붙은 클래스는 컴파일 시 컴파일러에 의해 하나로 합쳐집니다. 분할에는 제한이 없으며, 여러 번 분할해도 상관이 없습니다.


3. 중첩 클래스(Nested Class)


중첩 클래스는 클래스 내에 또 클래스가 정의된 클래스를 말합니다. 전에 배운 중첩 for, while, if문 등과 같이 클래스도 중첩이 가능합니다. 이 중첩 클래스는 주로 외곽 클래스에서만 사용하고자 할때, 외부에 정의하는 것보다 관련있는 클래스를 내부 클래스로 두어 코드를 쉽게 이해하기 위해 사용됩니다. 참고로, 내부에 쓰인 클래스는 제한자가 명시되어 있지 않으면 private로 보호 수준이 지정됩니다. 즉, A라는 클래스 안에 private로 지정된 B라는 클래스가 존재하면, B 클래스는 A 클래스 밖에서 보이지 않습니다. A 클래스 내에서만 사용이 가능합니다.

class 클래스명
{
    class 클래스명
    {
        ..
    }
}

아래는 중첩 클래스가 쓰인 예제입니다.

using System;

namespace ConsoleApplication21
{
    public class OuterClass
    {
        private int a = 70;

        public class InnerClass
        {
            OuterClass instance;

            public InnerClass(OuterClass a_instance)
            {
                instance = a_instance;
            }

            public void AccessVariable(int num)
            {
                this.instance.a = num;
            }

            public void ShowVariable()
            {
                Console.WriteLine("a : {0}", this.instance.a);
            }
        }
    }

    class Program
    {
        static void Main(string[] args)
        {
            OuterClass outer = new OuterClass();
            OuterClass.InnerClass inner = new OuterClass.InnerClass(outer);

            inner.ShowVariable();
            inner.AccessVariable(60);
            inner.ShowVariable();
        }
    }
}

결과:

a : 70

a : 60

계속하려면 아무 키나 누르십시오 . . .


코드를 보시면, 13~16행에서 InnerClass의 생성자에 OuterClass의 객체를 넘겨주어 instance 객체에 OuterClass의 객체인 a_instance를 가져옵니다. 그리고 18~21행에서는 매개변수 num을 받아 num 값을 가지고 instance 객체의 멤버 변수 a의 값을 수정합니다. 여길 보아, 안쪽에 정의된 클래스에서 바깥쪽에 정의된 클래스의 private 멤버에 접근할 수 있음을 의미합니다. 그리고 23~26행은 그 instance 객체의 멤버 변수 a의 값을 출력시킵니다.

  1. dreamer at 2012.10.11 09:57 신고 [edit/del]

    잘봤습니다. 날마다 새로운 내용알아가서 좋네요.^^ 설명도 쉽게해주셔서 이해도 빠르고. 좋은강좌 올려주셔서 감사합니다.ㅎ

    Reply
  2. 김승현 at 2012.10.20 20:23 신고 [edit/del]

    감사합니다~

    Reply
  3. 질문 at 2012.11.05 17:48 신고 [edit/del]

    InnerClass에서 OuterClass를 선언할 수 있는게 이해가 안됩니다.
    OuterClass를 정의하고 있고 그 안에서 InnerClass를 같이 정의 중인데 자기보다 상위 클래스를 선언한다는게 이해가 안되네요.

    Reply
    • BlogIcon EXYNOA at 2012.11.05 22:07 신고 [edit/del]

      이는 내부 클래스에서 내부 클래스를 감싸주고 있는 외부 클래스에 액세스 하기 위해 작성한 부분입니다. 외부 클래스에 액세스 하기 위해 외부 클래스를 생성자로 중첩 클래스에 전달했습니다.

      저 내부 클래스도 하나의 멤버로 보셔야 합니다. 저런 틀(class)만 존재할 뿐이지, 실제로는 39행과 같이 외부 클래스를 생성자로 넘겨주어야 제기능을 합니다. 15행의 저 코드는 아무런 문제가 없게 되는거죠.

  4. 박무진 at 2012.12.05 12:08 신고 [edit/del]

    확장메소드에서 5.Multiplication(2, 3) 이렇게 호출하는 것이 맞는지요?
    Multiplication(5, 2, 3) 이렇게 호출하는것이 아니라...

    Reply
  5. 키리형 at 2013.02.25 17:00 신고 [edit/del]

    감사합니다 ~

    Reply
  6. C#입문자 at 2013.04.05 16:33 신고 [edit/del]

    확장메소드 이해가 안 갔었는데, using 으로 선언하는 부분을 이해하고 나니 확 와닿았네요..^^ 감사합니다!!
    매번 소스 작성해서 컴파일할때마다 개념 이해하는데 도움이 많이 되고 있습니다^^

    Reply
  7. 똘스터 at 2013.04.10 14:29 신고 [edit/del]

    C# 독학하고있는데 책으로도 이해가 안됐던 부분들을 잘 설명해주셨네요!!

    너무감사합니다!!

    여기있는 포스팅들 다 읽어보려고요!

    잘보겠습니다!

    Reply
  8. Nate Moon at 2013.06.04 17:41 신고 [edit/del]

    잘 보고 갑니다 ^-^!

    Reply
  9. 용쿤 at 2013.10.14 17:53 신고 [edit/del]

    강의 감사드립니다. 저 질문이 있는데요.

    중첩class 내용 중 15번행에서 "OuterClass instance;" 라고 선언된 부분이 있는데요

    여기서 instance는 OuterClass의 객체이고 a = 70이란 정보가 자동으로 들어있는 건가요?

    아니면 OuterClass instance = new OuterClass(); 와 같은거라고 봐야되는지요

    클래스 이름 뒤에 바로 객체를 적는게 처음 접하다보니 이해가 가질 않습니다

    Reply
    • BlogIcon EXYNOA at 2013.10.15 20:37 신고 [edit/del]

      네 그렇습니다. 클래스 OuterClass의 멤버 변수 a는 70으로 초기화 되어있고, 38행에서 생성한 OuteClass 객체 outer를 InnerClass의 생성자로 넘겨주어 InnerClass 내의 instance를 초기화하는 것입니다.

  10. ZiNee at 2013.10.21 14:56 신고 [edit/del]

    강좌 감사합니다.

    Reply
  11. iamksu at 2014.09.25 16:54 신고 [edit/del]

    이번 강좌도 잘 봤습니다.

    Reply
  12. ehrbs at 2014.11.28 14:18 신고 [edit/del]

    강좌 감사합니다.
    제가 어떠한 책을 보면서 공부하고 있는데 이해가 안가서 질문 드립니다. ㅠ
    코드가
    public class HardDisk
    {
    class Platter{}
    Platter [] platter;
    }
    이렇습니다. 여기서 Platter[] platter의 의미가 대체 무엇인가요 ㅠ.
    왜 이렇게 적었는지 이유를 몰라서 질문드립니다.

    Reply
  13. C#을 배우고 싶어요 at 2014.12.23 17:58 신고 [edit/del]

    엑시노아님 이번 회차 강좌에 궁금한 점이 있습니다.
    바로 39행의 innerClass의 객체를 생성하는 부분인데요.
    innerClass가 생성자이기 때문에 객체를 생성하면서 바로 호출까지 하는걸로 알고 있습니다.
    그렇기 때문에 innerClass를 호출하며 매개변수로 outerClass의 객체인 outer를 넘겨주잖아요??

    그 부분이...이해가 어렵습니다..
    매개변수를 받는 쪽은 (변수타입 변수명)의 형태를 띄도록 되어 있는것 아닙니까??
    그렇다면 innerClass 생성자 메소드는 outerClass라는 타입을 a_instence 라는 이름으로 받는겁니까??

    Reply
    • BlogIcon EXYNOA at 2014.12.25 13:16 신고 [edit/del]

      네, 말씀하신대로 객체가 생성되면서 생성자가 호출되어 내부 클래스를 외부 클래스에 넘겨주는게 맞습니다. 내부 클래스 생성자가 a_instence라는 이름으로 넘겨받아 사용하는 것도 맞습니다.

  14. 오곡 at 2016.09.12 15:15 신고 [edit/del]

    좋은 공부하고 갑니다~!

    Reply
  15. 초보자 at 2016.10.20 08:59 신고 [edit/del]

    감사합니다!!

    Reply
  16. 쟝미 at 2017.04.06 16:23 신고 [edit/del]

    확장메서드를 사용하는 궁극적인 이유는 무엇인가요?? 클래스를 확장시킨다는게 어떠한 경우를 의미하는지 잘 모르겠습니다. ㅠㅠ 왜 쓰는지, 왜 생긴 문법인지가 궁금합니다.
    설명이 항상 깔끔하셔서 물어봅니다!!

    Reply
  17. ldi3492 at 2018.01.23 15:36 신고 [edit/del]

    앞선 14년 자료에 택배조회 프로그램 만드셨던데 제가 임의로 배송조회 시스템 비슷한걸 만들어야 하는데 좀 질문좀 드려도 될까요??
    메일로 답장좀 부탁드립니다. ldi3492@naver.com 입니다.

    Reply
    • BlogIcon EXYNOA at 2018.01.23 16:02 신고 [edit/del]

      질문이 여러 개가 아니라면 방명록에 남겨주시면 감사하겠습니다. 아니면 카카오톡으로 대화를 주셔도 괜찮습니다.

  18. sujub at 2018.09.14 22:48 신고 [edit/del]

    감사합니다~~ 설명을 축약해서 이리 잘올려주신자료 처음이네요 ㅠㅠ 최고세용~~

    Reply

submit

티스토리 툴바