ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • C# 시작
    @ 16. 1 ~ 17. 1/C# 2016. 11. 16. 21:26

    foreach(자료형 변수명 in 순차접근되는 배열?)


    포인터는 없으므로, ref int a 이렇게 ref붙이면 참조형식으로 변경됨..

    그런데 매개변수로 넘길땐느 ref를 붙여서 넘겨야 한다.

    static void Add(ref int a);

    함수일때 사용하면

    int a = 40;

    Add(ref a);

    out 키워드는 ref 키워드와 비슷하게 인수를 참조로 전달할때 사용됩니다. 그러나 차이점이 존재합니다. out 키워드를 사용하면 변수를 전달하기전 초기화해야하는 ref 키워드와는 달리 초기화 하지 않고도 전달이 가능합니다. 아래는 out 키워드의 사용 예제입니다

    위에 ref 랑 똑같음..

    ref와 out의 차이는 ref는 초기화를 해야하는데 out은 안해도 된다.


    우리가 만약, 길이에 제한받지 않고 수를 넘겨주어 그 수의 총 합을 구하고 싶을때는 어떻게 하면 될까요? 바로 params 키워드를 사용하면 쉽게 구할 수 있습니다. params 키워드의 기능은 메소드에 여러개의 값을 전달할 수 있도록 도와줍니다. 아래는 params 키워드가 사용된 예제입니다.


    데이터타입[] 배열명 = new 데이터타입[크기];      //1차원 배열

    데이터타입[,] 배열명 = new 데이터타입();    //2차원 배열

    데이터타입[,,] 배열명 = new 데이터타입(높이세로가로);


    클래스명 식별자 = new 클래스명();


    접근 제한자

    설명 

    private

    클래스 내부에서만 접근이 가능합니다.

    public 

    모든 곳에서 해당 멤버로 접근이 가능합니다.

    internal

    같은 어셈블리에서만 public으로 접근이 가능합니다. 

    protected

    클래스 외부에서 접근할 수 없으나 파생 클래스에서는 접근이 가능합니다.

    protected internal 

    같은 어셈블리에서만 protected으로 접근이 가능합니다.


    클래스명 앞에다 sealed 키워드를 사용하게 되면, 이 클래스를 상속시키는건 더이상 할 수 없습니다. 



    3. set, get

    set, get 접근자는 각각 속성을 읽거나, 새 값을 할당할 때 사용됩니다. 객체 지향 프로그래밍에서 정보은닉을 위해 클래스 내부에서만 사용할 수 있도록 private로 접근을 제한하여 버립니다. 그럼 외부에서 이 속성을 변경할수가 없죠? 그런데 프로그램을 만들다 보면, 내부 변수를 수정해야 할 상황이 벌어질 수도 있습니다. 그때 쓰이는 것이 set, get 접근자 입니다. get 접근자만 존재한다면 읽을 수만 있으며, set 접근자만 존재하면 쓸 수만 있으며, 두 접근자가 모두 존재하면 읽을 수도 있고, 쓸 수도 있게됩니다.
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
     
    namespace ConsoleApplication14
    {
        public class MyClass
        {
            private string name = "John";
     
            public string Name
            {
                get
                {
                    return name;
                }
                set
                {
                    name = value;
                }
            }
        }
        class Program
        {
            static void Main(string[] args)
            {
                MyClass mc = new MyClass();
     
                Console.WriteLine("mc.Name : {0}", mc.Name);
     
                mc.Name = "Bree";
                 
                Console.WriteLine("mc.Name : {0}", mc.Name);
            }
        }
    }

    결과:

    mc.Name : John

    mc.Name : Bree

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


    코드의 11줄을 보시면 name 속성이 private로 접근이 제한되어 있음을 알 수 있습니다. 그리고 13~23행에서 get, set 접근자가 등장합니다. Name이란 이름으로 get/set 접근자를 통해 name에 접근할 수 있으며, get 영역 내에서는 name의 값을 반환하고, set 영역 내에서는 name 속성에 value 값으로 초기화시킵니다. 여기서 value은 Name으로 넘어온 값이라고 생각하시면 됩니다. 31행에서는 mc.Name이 아직까지는 John이였다가, 33행을 거치고 35행에서 Bree로 바뀌게 됩니다. 


    그리고 get/set 접근자 내에서 value에 변화를 주거나, 주지 않을 수도 있습니다. 아래는 그 예제입니다.

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    public class MyClass
    {
        private string name = "John";
     
        public string Name
        {
            get
            {
                return name;
            }
            set
            {
                if (value.Length < 5)
                    name = value;
            }
        }
    }
    class Program
    {
        static void Main(string[] args)
        {
            MyClass mc = new MyClass();
     
            Console.WriteLine("mc.Name : {0}", mc.Name);
     
            mc.Name = "Kelley";
             
            Console.WriteLine("mc.Name : {0}", mc.Name);
        }
    }

    결과:

    mc.Name : John

    mc.Name : John

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


    요번에는 set 접근자 영역 내를 잘 보면 value의 길이가 5보다 작아야 새 값을 할당할 수 있습니다. 만약에 5보다 같거나 크면 어떻게 될까요? 이번에는 Name에 Kelley를 넣어본 뒤에, 변화가 있나 결과를 살펴보았습니다. 결과를 봤더니, 새 값이 할당되지 않고 John 그대로 값이 유지되어 있었습니다. Kelley의 길이는 6이므로 초기화 되지 않고 빠져나와 버린것이죠.



    C#에서의 Override 키워드

    부모 클래스의 메소드를 자식 클래스에서 다시 정의하고 싶을때 virtual, override 키워드가 사용됩니다. 자세히 말하자면, virtual 키워드는 자식 클래스에서 메소드를 재정의 하고 싶을때 재정의 될 부모 클래스의 메소드에 사용되며, override 키워드는 부모 클래스 내에서 virtual로 선언된 메소드를 재정의 하겠다는 표시를 하는것과 같습니다. (이 말고도 추상 구현 등에서 사용되기도 합니다.)

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
     
    namespace ConsoleApplication21
    {
        class Parent
        {
            public virtual void A()
            {
                Console.WriteLine("부모 클래스의 A() 메서드 호출!");
            }
        }
        class Child : Parent
        {
            public override void A()
            {
                Console.WriteLine("자식 클래스(Child)의 A() 메서드 호출!");
            }
        }
        class Daughter : Parent
        {
            public override void A()
            {
                Console.WriteLine("자식 클래스(Daughter)의 A() 메서드 호출!");
            }
        }
     
        class Program
        {
            static void Main(string[] args)
            {
                Parent parent = new Parent();
                parent.A();
     
                Child child = new Child();
                child.A();
     
                Daughter daughter = new Daughter();
                daughter.A();
            }
        }
    }

    결과:

    부모 클래스의 A() 메서드 호출!

    자식 클래스(Child)의 A() 메서드 호출!

    자식 클래스(Daughter)의 A() 메서드 호출!

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


    코드의 11행, 18행, 25행을 보시면 각각 virtual, override, override가 등장했습니다. 알아두셔야 할 점은, 메소드를 재정의 하려면 virtual 키워드가 붙어 있어야 한다는 겁니다. 만약 virtual 키워드가 붙어있지 않다면, 컴파일러는 다음과 같은 에러를 내보냅니다.


    오류 1 'ConsoleApplication21.Child.A()': 상속된 'ConsoleApplication21.Parent.A()' 멤버는 virtual, abstract 또는 override로 표시되지 않았으므로 재정의할 수 없습니다. C:\Users\h4ckfory0u\documents\visual studio 2012\Projects\ConsoleApplication21\ConsoleApplication21\Program.cs 18 30 ConsoleApplication21


    재정의될 메서드에 virtual로 표시되지 않으면 재정의를 할 수 없다는 에러입니다. 즉, 재정의 될 메서드에는 virtual로 한정되어 있어야 하며, 이것을 오버라이딩 하기 위해 override 키워드를 사용합니다. 한가지 더 말씀드리자면, private로 보호 수준이 지정된 메서드는 재정의 할 수 없습니다.


    C++11 에서의 Override 키워드
    자식 클래스에서 선언되어 있는 가상 함수에 override 키워드를 붙이면,
    부모 클래스에 반드시 동일 시그너처를 가지는 가상 함수가 선언되어 있어야 한다.

    부모 클래스에 선언되어 있지 않은 형태의 멤버 함수에 override 키워드를 붙이면, 
    아래와 같은 컴파일 에러가 발생한다.

    error C3668: 'XXXClass::FuncA' : 재정의 지정자 'override'가 있는 메서드가 기본 클래스 메서드를 재정의하지 않았습니다.

    이를 잘 활용하면, 부모 클래스의 가상 함수를 상속 받는답시고,
    자식 클래스에서 시그너처를 다르게 선언해 전혀 다른 함수를 만들어 내는 것을 피할 수 있다.

    override 키워드는 아래와 같이 사용한다.

    function-declaration override;

    즉, 함수의 const 키워드를 붙이는 것과 같이 함수 선언 뒤에 override 키워드를 붙이면 된다.

    확실히 이해하기 위해 override 관련 MSDN 페이지 에서 따온 예제를 보자.

    1. class BaseClass
    2. {
    3.     virtual void funcA();
    4.     virtual void funcB() const;
    5.     virtual void funcC(int = 0);
    6.     void funcD();
    7. };
    8.  
    9. class DerivedClass: public BaseClass
    10. {
    11.     // 부모와 동일한 시그너처의 가상 함수이므로 OK
    12.     virtual void funcA() override;
    13.    
    14.     // 부모의 funcB는 const 한정자가 있으므로, DerivedClass의 funcB는 다른 함수
    15.     // 따라서, 컴파일 에러
    16.     virtual void funcB() override;
    17.  
    18.     // 부모의 funcC의 인자 타입과 자식의 인자 타입이 다르다. 즉, 다른 함수
    19.     // 따라서, 컴파일 에러
    20.     virtual void funcC(double = 0.f) override;
    21.  
    22.     // 비가상 함수는 override 키워드 불가, 컴파일 에러
    23.     void funcD() override;
    24. };

    참고로, override 키워드는 vs2005 버전부터 지원한다.
    하지만, vs2005 ~ 2010까지는 비표준 확장을 사용했기에, 경고 레벨을 4로 올리면 아래와 같은 컴파일 경고가 발생한다.

    warning C4481: 비표준 확장이 사용되었습니다. 'override' 지정자를 재정의합니다.

    vs2012 즉, C++11 부터는 표준이기에 경고가 발생하지 않는다.



    5. 멤버 숨기기(new)

    new 지정자를 사용하면 부모 클래스의 멤버를 숨길 수 있게됩니다. 물론, 부모 클래스에서 정의된 메소드, 멤버 변수의 이름이 자식 클래스에도 같은 이름으로 존재한다면 부모 클래스의 멤버는 new 지정자를 사용하지 않아도 숨길 수 있으나, 부모 클래스의 멤버가 숨겨진다는 경고가 발생합니다. 이 경고는 new 지정자를 사용하면 사라집니다. 

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
     
    namespace ConsoleApplication21
    {
        class Parent
        {
            public int x = 100;
            public void A()
            {
                Console.WriteLine("부모 클래스의 A() 메서드 호출!");
            }
        }
        class Child : Parent
        {
            public new int x = 200;
            public new void A()
            {
                Console.WriteLine("자식 클래스(Child)의 A() 메서드 호출!");
            }
        }
     
        class Program
        {
            static void Main(string[] args)
            {
                Parent parent = new Parent();
                parent.A();
                Console.WriteLine("x : {0}", parent.x);
     
                Child child = new Child();
                child.A();
                Console.WriteLine("x : {0}", child.x);
            }
        }
    }

    결과:

    부모 클래스의 A() 메서드 호출!

    x : 100

    자식 클래스(Child)의 A() 메서드 호출!

    x : 200

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


    new 키워드를 붙이지 않아도 컴파일 하는데는 지장이 없습니다. 다만 경고가 발생할 뿐이에요.


    클래스의 상속편은 여기서 마치도록 하겠습니다. 수고하셨습니다.


    다음 강좌에서는 확장 메소드, 중첩 클래스, 분할 클래스에 대해 배워보도록 하겠습니다.



    감사합니다. 참고로 위 강좌 보시고 override와 new의 차이점이 구분이 안가시는 분들은 아래 URL보시기 바랍니다.

    http://msdn.microsoft.com/ko-kr/library/ms173153(v=vs.80).aspx

    간단히 얘기하자면 아래처럼 실행됩니다.

    Parent p = new Child();

    <override> 
    - p.A(); 실행시 "자식 클래스(Child)의 A() 메서드 호출!" 출력
    <new> 
    - p.A(); 실행시 "부모 클래스의 A() 메서드 호출!" 출력
    - 분명 child()로 생성했음에도 p의 타입이 Parent여서 Parent의 함수가 실행됨
    - Child c = new Child();일 때 p.A(); 실행시 "자식 클래스(Child)의 A() 메서드 호출!" 출력됨



    선언 한정자로 사용되는 new 키워드는 기본 클래스에서 상속된 멤버를 명시적으로 숨깁니다. 상속된 멤버를 숨기면 파생 버전의 멤버로 기본 클래스 버전의 멤버를 대신하게 됩니다

    new 한정자를 사용하지 않고 멤버를 숨길 수도 있지만 컴파일러 경고가 발생합니다. new를 사용하여 멤버를 명시적으로 숨기면 이 경고가 발생하지 않습니다.


    참고사이트

    https://msdn.microsoft.com/ko-kr/library/435f1dw2.aspx 




    C# 확장메소드

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

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    namespace 네임스페이스명
    {
        public static class 클래스명
        {
            public static 반환형식 메소드명(this 확장대상형식 식별자, 매개변수..)
            {
                ..
            }
        }
    }

    확장 메서드는 메서드가 사용될 클래스명(혹은 Type)을 첫번째 파라미터로 지정하여 마치 해당 클래스(혹은 Type)가 확장메서드를 인스턴스 메서드로 갖는 것과 같은 효과를 낸다. 약간 특이한 문법이지만, 확장 메서드의 첫번째 파라미터는 앞에 항상 this를 써준다




    2. 분할 클래스(Partial Class)


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

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
     
    namespace ConsoleApplication21
    {
        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 키워드가 붙은 클래스는 컴파일 시 컴파일러에 의해 하나로 합쳐집니다. 분할에는 제한이 없으며, 여러번 분할해도 상관이 없습니다.



    C# 구조체 클래스와 C++ 구조체 클래스의 차이

    클래스는 힙에 생성되는 참조 타입(Reference Type)이고, 구조체는 스택에 생성되는 값 타입(Value Type)이라는 것이죠. 구조체는 클래스보다 메모리 소모가 덜하므로 어떤 개발자들은 구조체를 더 선호하기도 합니다. 아래는 구조체의 선언 형식입니다.


    각각 new 연산자로 구조체의 객체를 생성하고, 반대로 39~45행을 보시면 new 연산자를 사용하지 않고 선언만으로도 인스턴스화 할 수 있습니다. 값 타입(Value Type)인 구조체는, 이처럼 바로 접근이 가능하고 서로 대입이 가능합니다. 이렇게 구조체는 C#에서 크기가 작거나, 내부가 그렇게 복잡하지 않을때. 즉, 작고 단순한 메서드를 포함하고 있는 선, 컬러같은 그래픽 요소 등을 구조체로 정의합니다.


    new 를 이용한 구조체 생성


    Person mother = new Person(40, 160L, 60F);

     



    - 값타입의 메모리구조


    값타입의 경우 메모리가 자동으로 생성되는 이유는 내부에서 new연사자를 자동으로 호출하기 때문이다. 알고보면 값타입도 new연사자로 메모리를 생성하지만 그 행위는 묵시적으로 일어난다.


    int a; 라는 구문은 int a = new int();와 같이 해석된다.

    결론적으로 값타입과 참조타입은 둘다 new연산자를 이용해서 메모리를 생성한다.


    C# .NET의 기본 데이타형들은 struct로 정의되어 있다. 즉, int, double, float, bool 등의 기본 데이타 타입은 모두 struct로 정의된 Value Type이다. Value Type은 상속될 수 없으며, 주로 상대적으로 간략한 데이타 값을 저장하는데 사용된다.


    참조 형식(Reference Type)

    참조 형식은 string, object, class와 같은 형식으로 new를 통하여 인스턴스가 생성이 되면 데이터를 참조하는 메모리 주소만 가지고 있으며, 실제 데이터는 분리된 공간에 저장이 된다. 참조 형식은 기존의 변수를 새로운 변수에 할당할 경우 값 전체를 복사 하는 것이 아니라, 값을 참조하는 주소를 복사하게 된다.


    var로 선언된 변수는 모든 형식을 사용할 수 있지만, 차이점은 한번 선언된 형식은 불변으로 선언된 이후에 다른 형식의 값으로 설정 할 수 없다.



    object vs. var vs. dynamic]

    여러 가지 변수 설정 방식 및 형식 설정에 대해 살펴 보았다. 하지만 기존의 object, var, dynamic 형식이 비슷한 면이 존재 하면서도 각각의 차이점이 존재한다.

    공통점은 모두 다양한 형식을 값으로 설정이 가능하다.

    차이점은 아래 그림을 보면 분명히 보인다.

    object에 할당된 형식은 어떤 형식이든 object로 변환이 된다. 인텔리센스를 보면 이해가 빠를 것이다. 다시 원본 형식을 사용하고 싶으면 형 변환 작업이 필요하다.

     061611_1204_05DataType21.png

    [object로 선언하였을 경우 인텔리센스 표시]

     

    var 형식은 값이 설정되는 시점에 형식을 추정하여 설정된 형식 그 자체 이다. 아래 인텔리센스를 보면 문자열 값을 설정 하였을 경우 문자열 관련 메서드가 보이는 것을 확인 할 수 있다.

     061611_1204_05DataType22.png

    [var로 선언하였을 경우 인텔리센스 표시]

     

    dynamic은 인텔리센스가 동작하지 않는다. 왜냐하면 컴파일 시점에는 어떤 형식인지 확인을 하지 않고 런타임 환경에서 확인을 하기 때문이다. 이러한 경우는 개발자가 사용하고자 하는 메서드 등의 멤버에 대해 정확히 알고 있다는 가정이 필요하다. 만약 잘못된 메서드를 사용하였어도 컴파일에서는 밸리데이션(Validation)을 하지 않기 때문에 아무 빌드 오류를 발생하지 않기 때문이다. 그러므로 성능상의 이슈와 런타임 환경에서 형식이 확정 되기 때문에 예기치 않은 오류를 야기 할 수 있다. 주의 깊게 사용하여야 한다.

     061611_1204_05DataType23.png

    [dynamic으로 선언하였을 경우 인텔리센스 표시]

     

    object

    var

    dynamic

    설정 가능한 형식

    모든 형식

    null 등 일부를 제외한 대부분의 형식

    모든 형식

    설정 값의 원본 유지

    값을 설정하면 object 형식 그 자체

    원본 형식을 추정

    개발 시점에서는 원본 형식을 알 수 없음

    형식 확정

    컴파일(object 자체)

    컴파일

    런타임

    바인딩 방식

    정적

    정적

    동적



    이와 더불어 C#에서는 const와 비슷한 readonly를 지원한다.

    공통점은 모두 초기화 이후에는 값을 변경 할 수 없다. 하지만 const는 선언할 때만 초기화될 수 있다. readonly는 선언할 때 또는 생성자에서 초기화될 수 있다. 따라서 readonly 필드의 값은 사용된 생성자에 따라 다르다. const는 컴파일 타임 상수, readonly는 런타임 상수로 불리우기도 한다.




    C# Interface 란?

    자, 이제 이런 인터페이스를 어떻게 정의하고 어떻게 사용되는지 예제를 통해 알아보도록 합시다. 우선 아래는 interface 키워드를 사용하여 인터페이스를 정의하는 예입니다.

    1
    2
    3
    4
    interface 인터페이스명
    {
         // ...
    }

    인터페이스 내에서는 메소드, 이벤트, 인덱서, 속성이 쓰일 수 있으며, 필드를 포함할 수 없습니다. 그리고 인터페이스의 모든 멤버는 public로 접근 권한이 기본으로 지정됩니다. 대충 보아하니 클래스와 선언하는 방법이 비슷하죠? 맞습니다. 인터페이스는 말하자면 클래스의 한 종류라고도 말할 수 있습니다. 그러나 인터페이스 내에 쓰인 멤버는 구현부를 가지지 않습니다. 즉 몸통은 없이 정의되어 있어, 직접 호출할 수 없는 추상적인 멤버를 가집니다. 한가지 더 알아두셔야 할것이 있는데, 클래스의 상속에 대한 얘기를 다시한번 꺼내려고 합니다. 강좌를 거슬러 올라가서, 우리는 부모 클래스를 상속받은 자식 클래스는 여러개 존재할 수 있으나, 부모 클래스가 여러개 존재할 수 없습니다. 한마디로 말하자면 클래스는 다중 상속이 불가능하고 단일 상속만 할 수 있으나, 인터페이스 같은 경우는 다중 상속이 가능하다는 특징을 가지고 있습니다. 한번 지금까지 말한 인터페이스의 특징을 간략하게 정리해봅시다.


        인터페이스 내에서는 메소드, 이벤트, 인덱서, 속성을 쓸 수 있습니다.

        인터페이스에서는 필드를 포함할 수 없습니다.

        모든 멤버는 public로 접근 권한이 기본으로 지정됩니다.

        몸통이 정의되어 있지 않은 추상적인 멤버를 가집니다.

        인터페이스는 다른 인터페이스를 상속하거나, 클래스에서 인터페이스 하나를 여러 차례 상속할 수 있습니다.


    참고로 C#에서의 상속은 public상속만 된다.


    as 연산자와 is 연산자 

    C#의 as 연산자는 객체를 지정된 클래스 타입으로 변환하는데 사용된다. 만약 변환이 성공하면 해당 클래스 타입으로 캐스팅하고, 변환이 실패하면 null 을 리턴한다. 

    이와는 대조적으로 암묵적 캐스팅(Implicit Casting)은 만약 변환이 실패하면 Exception을 발생시키게 되는데, 이를 catch하지 않은 경우 프로그램을 중지시키게 된다.

    C#의 is 연산자는 is 앞에 있는 객체가 특정 클래스 타입이나 인터페이스를 갖고 있는지 확인하는데 사용된다.
     \


    #. as 연산자
     - as 연산자는 형식 변환 연산시 사용됩니다. 다만 캐스트 연산과 다른 점은 변환이 가능하지 않는 경우 예외를 발생하지 않고 null이 반환된다는 것입니다. 즉, as 연산자는 as 뒤에 나오는 타입이 아니면 null을 반환 합니다. 
     - as 연산자는 오직 참조 변환과 boxing 변환만을 수행하며, 사용자 정의 변화과 같은 다른 변환을 수행할 수 없습니다.

    ex>
        static void Main()
        {
            object[] objArray = new object[3];
            objArray[0] = "hello";
            objArray[1] = 123;
            objArray[2] = null;

            for (int i = 0; i < objArray.Length; ++i)
            {
                string s = objArray[i] as string;
                Console.Write("{0}:", i);
                if (s != null)
                {
                    Console.WriteLine("'" + s + "'");
                }
                else
                {
                    Console.WriteLine("not a string");
                }
            }
        }

    결과 값>
    0:'hello'
    1:not a string
    2:not a string

    #. is 연산자
     - 특정 객체와의 타입과 호환이 가능한지 확인하는 연산자 입니다. 
     - 호환이 가능한 경우 true를 반환하고, 호환이 가능하지 않은 경우 예외를 발생하지 않고 false를 반환합니다.
     - is 연산자는 참조 변환, boxing 변환, unboxing 변환만을 수행하며, 사용자 정의 변환과 같은 다른 변환은 고려되지 않습니다.

    ex>
    string strTemp = new string();

    Bool b1 = (strTemp is string);
    Bool b2 = (strTemp is int);

    Console.WriteLine("b1: {0}, b2: {1}", b1, b2);

    결과 값>
    b1: true, b2: false



    앞에서 인터페이스의 특징을 설명하다보니 상속이란 말이 나오게 되었는데, 우리가 지금까지 알고있는건 클래스의 상속 뿐이었습니다. 클래스가 클래스를 상속할 수 있듯이, 인터페이스가 인터페이스를 상속할 수 있습니다. 형식은 클래스의 상속과 다르지 않습니다.

    1
    2
    3
    4
    interface 자식인터페이스명 : 부모인터페이스명
    {
       // ...
    }

    아래 예제에서는 인터페이스를 인터페이스에 상속하고 다시 이 인터페이스를 클래스로 상속했습니다.


    인터페이스는 추상적인 멤버를 가진다고 하셨는데, 그럼 인터페이스는 반드시 하나 이상의 클래스를 상속해야 

    '@ 16. 1 ~ 17. 1 > C#' 카테고리의 다른 글

    getter setter  (0) 2016.11.18
    C# 시작2  (0) 2016.11.16
    C# 3교시...  (0) 2014.07.27
    C# 2교시...C++차이점위주..  (0) 2014.07.26
    C# 시작하다...  (0) 2014.07.25
Designed by Tistory.