Post

[C#] Lec 08 - 프로퍼티, 인덱서

[C#] Lec 08 - 프로퍼티, 인덱서

프로퍼티(property)

프로퍼티의 존재 이유

1
2
3
4
5
6
7
8
9
10
11
12
class MyClass
{
	int myField;
	public int GetMyField()
    {
		return myField;
    }
	public void SetMyField(int value)
    {
		myField = value; // getter, setter를 따로 구현해야함.
    }
}
  • 위 코드 : 프로퍼티가 아닌 필드를 이용하여 getter, setter를 구현한 경우
  • 필드에 은닉성을 부여하기 위해 주로 필드를 private 접근자로 제한하고 일반적으로 getter/setter 메소드를 활용함.
  • public 접근자를 안쓴 필드는 모두 프로퍼티.
  • 귀찮음 해소를 위해 필드 자체를 정의 하는 것을 생략하는 방법이 추가됨
  • 굳이 getter method를 만들지 않게 하기 위해 value를 사용.

프로퍼티의 사용

1
2
3
4
5
6
7
8
9
10
class MyClass 
{
  public int MyField {
    get;set;
  }
  public int MyField2 {
    get;
  }
}
  • 프로퍼티 내에 필드가 정의되지 않은 것 처럼 보이지만 실제로 동작 시에는 가상의 필드를 만들어 동작함.
  • getter method만을 구현할 경우 무조건 생성자에서만 set하고 Class 내부, 외부에서 모두 설정을 바꿀 수 없게 됨.
  • getter setter 가 모두 구현되어 있다면 클래스 내부, 외부에서 모두 값 확인 및 변경이 가능
1
2
3
4
class Dog 
{
  public string Name => "asdf";
}
1
2
3
4
5
6
7
8
9
class Dog 
{
  string _name = "asdf";
  public string Name
  {
    get {return _name;}
    set {_name = value;}
  }
}
  • 위 두 코드는 완벽히 일치

프로퍼티의 초기화

  • setter 메소드가 만들어 져 있는 프로퍼티의 경우에는 생성자를 만들지 않고도 인스턴스 생성과 동시에 초기화시켜줄 수 있음
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
class Dog
{
  public int Number {
    get;set;
  }
  public int Number2 {
    get;set;
  }
  public int Code {
    get;
  }
  public Dog(int a, int b) {
    Number = a;
    Code = b;
  }
}
class Program
{
  public static void Main(string[] args)
   {
     Dog asdf = new Dog(1,1);
     Dog fdsa = new Dog() {
       Number = 2, Number2=3
       //, Code=3
     };

   }
}
  • 문법에 주의 : Instance 생성할때 기본 생성자로 초기화시키려면 기본생성자()와 ; 사이에 코드블럭 만들고 프로퍼티=값, 프로퍼티는 값 입력. 여기에는 세미콜론 넣으면 안됨. 코드블럭이 끝난 뒤 ; 입력해 주어야 함.
  • 당연히 set 메소드가 구현되지 않은 프로퍼티의 경우 인스턴스 생성시 초기화 못함

인터페이스와 프로퍼티

  • 인터페이스에서 필드를 만들 수 없는 이유 : 인스턴스 화 즉 인터페이스를 객체로 선언할 수 없기 때문
  • 인터페이스에서 프로퍼티를 만든다 -> 메서드를 만드는것과 동일한 개념이므로,
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
interface IDog
{
  public string Name{get;set;}
  public string Color{get;}
}
class Dog : IDog
{
  private string _name;
  public string Name
  {
    get {return _name;}
    set {_name = value;}
  } //Interface에서 구현하라고 한 것을 구현한 모습
  //Color 또한 get method를 구현해야함
}

추상 클래스와 프로퍼티

  • 추상 클래스를 상속받는 이유 : 추상 메소드를 만들 수 있음. (구현이 있는 프로퍼티 + 구현이 없는 프로퍼티를 만들 수 있음)
  • 추상클래스에서 구현한 추상 프로퍼티를 추상 클래스를 상속받은 클래스에서 다시 재정의해야함. (override 키워드를 이용하여)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
abstract class BaseClass
{
  public int Property1 {get;set;} //구현을 가진 프로퍼티
  abstract int Property2 {get ;set;} //구현이 없는 프로퍼티
}

class MyClass : BaseClass
{
  public override int Property2
  {
    get;
    set;
  } // abstract class에서 abstract method로 정의된 것은 자손 클래스에서 override 키워드로 재정의해야함
}

인덱서(Indexer)

  • 객체를 배열처럼 사용하기 위하여 만든 것 : 인덱서
1
2
3
4
5
6
7
8
9
10
public class MyList 
{
  int[] _array = new int[10];
  public int this[int index]
  {
    get {return _array[index];}
    set {_array[index] = value;}
  }
}
  • 인덱서를 이용하여 객체 자체를 배열처럼 이용할 수 있음
  • index의 값에 의한 오류처리는 get,set 메소드 안에서 처리해줘야함
  • indexer 또한 프로퍼티와 같이 객체 내부의 값에 접근하기 위한 통로 역할을 함
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
public class MyList 
{
  int[] _array = new int[10];
  public int this[int index]
  {
    get {return _array[index];}
    set 
    {
      if (index>=_array.Length)
        Array.Resize<int>(ref _array, index+1);
      _array[index] = value;
    }
  }
  public int Length {get {return _array.Length;}}
}
class Program 
{
  public static void Main(string[] args)
  {
    MyList ml = new MyList()
    for (int i = 0; i<=myList.Length; i++) 
    {
      Console.WriteLine(myList[i]);
    }
  }
}

IEnumerator, IEnumerable 상속

  • Foreach를 넣기 위해서는 인터페이스를 상속받아야만 함
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
public class MyList : IEnumerable
{
  int[] _array = new int[10];
  public int Length { get { return _array.Length; } }
  public int index { get; set; }
  public int this[int index]
  {
    get { return _array[index]; }
    set
    {
      if (index >= _array.Length)
        Array.Resize<int>(ref _array, index + 1);
      _array[index] = value;
     }
  }
  public IEnumerator GetEnumerator()
  {
    for (int i = 0; i< _array.Length; i++)
    {
      yield return _array[i];
    }
  }
}
This post is licensed under CC BY 4.0 by the author.