[C#] 객체 this[] indexer 기능

·2024년 11월 12일
0

Unity

목록 보기
11/11

C#의 프로퍼티 기능을 사용하다가 그저 자료의 get/set 정의뿐만이 아닌 this[]라는 인덱서 기능이 있다는 글을 보고 직접 사용해보고 이를 글로 남기기로 했다!

🤷🏻‍♀️어쩌다 이 문법을 알게 되었는가?

최근에 UI 리팩토링 작업을 진행중이다. 그래서 MVP 패턴으로 기존 skill관련 스크립트속 UI들을 SkillPresenter 스크립트로 분리하는 작업도중, 프로퍼티 기능을 자주 사용하게 되었다.

UI가 갱신되어야 할 데이터가 변경되면, 값을 업데이트해주는 동시에 action을 통해 대리자 함수를 invoke하는 식으로 presenter를 호출하고 있었다.

public struct data{ ~ }
public class Skill {
	Dictionary<enum, data> active;
	public Dictionary<enum, data> refActive{
    	get { return active; }
        set { 
        	active = value;
        	activeAction.Invoke();
    	}
    }
    public Action aciveAction;
}

public class SkillPresenter {
	public Skill m_skill;
	void start(){
    	m_skill.activeAction += UpdateActiveUI;
    }
    void UpdateActveUI();
}

위와 같은 형식으로 데이터를 갱신해주는데, 값 전체를 덮어쓰는 것이 아닌 특정 enum key에 대해서만 값이 갱신되고 그 변경 값에 대해서만 대리자를 호출해주고 싶었다.

그때 구글링을 하며 어떻게 하면 set 프로퍼티에 갱신되는 enum을 넘겨줘서 dictionary에 접근이 가능할지 구글링을 하던 중, 이 문법을 알게된 것이다.

👩🏻‍💻 언제, 어떻게 사용하는 문법인가?

처음에 맨땅에 헤딩 느낌으로 객체가 아닌 변수에 해당 문법을 사용해서 원하는 결과가 나오지 않았다.

public struct data{ ~ }
public class Skill {
	Dictionary<enum, data> active;
	public Dictionary<enum, data> refActive{
    	get { return active; }
    }
    public data this[enum slot]{
    	get{ return active[slot];
        set{
        	active[slot] = value;
            activeAction.Invoke(slot);
        }
    }
    public Action<enum> aciveAction;
}

📍이 인덱서 기능은 객체 인스턴스에 대해 원하는 형태로 프로퍼티를 활용해 접근/갱신하기 위해 정의된 문법이다.

따라서 위 처럼 하는 것이 아닌, 하나의 class에 객체를 new 생성하고 그 객체에 대해 배열처럼 인덱스 접근을 해주면, 원하는 프로퍼티를 호출한다!

public struct data{ ~ }
public class Active{
	Dictionary<enum, data> skill;
    public Dictionary<enum, data> refSkill{
    	get { return active; }
    }
    public data this[enum slot]{
    	get{ return active[slot];
        set{
        	active[slot] = value;
            activeAction.Invoke(slot);
        }
    }
    public Action<enum> aciveAction;
}
public class Skill {
	public Active activeSkill = new Active();
    
    void Start(){
    	activeSkill[enum:slot] = data;
    }
}

⚖️ this를 정의할 때,

  1. 대괄호 안에 어떤 식별자로 프로퍼티에 접근할 것인지
  2. 어떤 데이터를 넣을 것인지(-> value의 자료형) 정의하면 된다.
    나는 dictionary의 key값을 식별자로 원하는 데이터를 갱신하는 식으로 해당 인덱서를 사용하고 대리자를 호출해줬다!

🦚 Variation

  • 동일 class내에 반환 타입이 다르더라도 식별자가 동일하면 오버로딩이 안된다.
public bool this[enum slot] {get; set;}
public int this[enum slot] {get; set;} // error : CS0111

  • 대괄호에 여러 식별자를 넣을 수 있다.
// ------------ 정의
public bool this[enum slot, data _data] {get; set;}
public int this[enum slot, int num] {get; set;}
// ------------ 접근은 아래와 같이
data dataA = new data();
int cumulativeCoefficient = 0;
active[slot, dataA] =  true;
active[slot, cumulativeCoefficient] = cumulativeCoefficient+1;

그래서 어느정도 내가 원하는 방식으로 프로퍼티를 활용할 수 있다!

  • 제네릭을 활용하여 식별자와 반환타입의 자유도를 높일수 있다!
public struct data{ ~ }
public class Active<T>{
	Dictionary<T, data> skill;
    public Dictionary<enum, data> refSkill{
    	get { return active; }
    }
    public data this[T slot]{
        set{
        	active[slot] = value;
            activeAction.Invoke(slot);
        }
    }
    public Action<T> aciveAction;
}
public class Skill {
	public Active<int> activeSkill_1 = new Active<int>();
    public Active<string> activeSkill_2 = new Active<string>();
}

get/set 메소드를 정의하여 사용하는 것보다 오버헤드를 방지할수 있고 좀 더 직관적인 구현을 보여줄 수 있어서 객체지향적 프로그래밍에 정말 좋은 문법인거 같다.

profile
할 수 있는 최선을 다하는 클라이언트 개발자랍니다 (❁´◡`❁)

0개의 댓글

관련 채용 정보