<Extention> (확장 메서드)
- 확장 메서드를 사용하면 기존 형식에 메서드를 "추가"할 수 있다.
- 주로 readonly나 상속 불가능한 클래스에 필요한 기능을 추가할 때 사용한다.
- 확장 메서드와 일반 메서드를 호출하는 데는 명백한 차이가 없다고 한다.
- 확장 메서드는 정적 메서드이지만 확장 형식의 인스턴스 메서드인 것처럼 호출된다.
놀랍게도 가장 일반적인 확장 메서드는 (쿼리 기능을 기존 System.Collections.IEnumerable 및 System.Collections.Generic.IEnumerable<T> 형식에 추가하는) LINQ 표준 쿼리 연산자라고 한다!
<사용>
- static 클래스를 만든 후 확장메서드로 사용할 static 메서드를 만든다.
- 확장하려는 클래스를 매개변수의 첫번째로 두고 앞에 키워드 this를 붙인다.
- 확장하려는 클래스의 인스턴스 뒤에 dot을 찍고 확장 메서드를 사용한다.
<예>
Sealed Class
유니티의 GameObject.
namespace UnityEngine
{
public sealed class GameObject : Object
{
public GameObject();
public GameObject(string name);
public GameObject(string name, params Type[] components);
...
}
}
GameObject의 경우 sealed class이기 때문에 사용자가 임의로 메소드를 추가하기 어렵다.
public class SomeClass
{
// gameObject의 위치를 변화시킨 뒤
// 이름과 위치를 로그로 표시하는 메서드
public void Method_A(GameObject gameObject, Vector3 vec)
{
gameObject.transform.position += vec;
Debug.Log($"이름 : {gameObject.name}, 위치 : {gameObject.transform.position}");
}
// 사용시
public void Use_Method_A()
{
GameObject gameObject = new GameObject();
Mothod_A(gameObject, Vector3.forward);
}
}
일반적인 상황에서는 SomeClass 내부에 GameObject에 원하는 명령을 실행하는 함수를 따로 만들어 사용하지만
public static class Extension
{
public static void Method_B(this GameObject gameObject, Vector3 vec)
{
gameObject.transform.position += vec;
Debug.Log($"이름 : {gameObject.name}, 위치 : {gameObject.transform.position}");
}
}
public class SomeClass
{
// gameObject의 위치를 변화시킨 뒤
// 이름과 위치를 로그로 표시하는 메서드
/*public void Method_A(GameObject gameObject, Vector3 vec)
{
gameObject.transform.position += vec;
Debug.Log($"이름 : {gameObject.name}, 위치 : {gameObject.transform.position}");
}*/
// 사용시
public void Use_Method_B()
{
// 1번
GameObject gameObject = new GameObject();
gameObject.Mothod_A(Vector3.forward);
// 2번
GameObject gameObject = new GameObject().Mothod_A(Vector3.forward);
}
}
확장 메서드를 사용하면 마치 Method_B()가 GameObject의 메서드인 것처럼 쓸 수 있다.
Readonly Property
Transform.position. x,y
public class SomeClass
{
// 일반적으로 변경할 수 없는 Transform.position.x,y
public void Change_X()
{
transform.position = new Vector3(3, tr.position.y);
}
}
public static class Extension
{
public static void x(this Transform tr, float change)
{
tr.position = new Vector3(change, tr.position.y);
}
public static void y(this Transform tr, float change)
{
tr.position = new Vector3(tr.position.x, change);
}
}
public class SomeClass
{
// 확장메서드에서 추가한 메서드로
// Transform의 메서드처럼 간편하게 사용할 수도 있다.
public void Change_eachPos()
{
transform.x(3);
transform.y(-2);
}
}
<그 외>
확장 메서드는 이름과 시그니처가 클래스에서 이미 구현된 일반메서드와 정확하게 일치할 경우 호출되지 않는다.
①일치하는 시그니처를 가진 인스턴스 메서드를 찾을 수 없으면 => ②컴파일러는 일치하는 확장명 메서드(있는 경우)에 바인딩한다.
확장메서드는 클래스의 수정이 불가능해 코드가 불필요하게 반복될때 매우 유용한 기능인 것 같다.
'C#' 카테고리의 다른 글
[C#] 부동소수점 ( + int의 float 변환) (0) | 2021.11.24 |
---|---|
[C#] GC 가비지 컬렉션 (0) | 2021.10.17 |
[C#][Unity] is as 캐스팅 연산자 (0) | 2021.08.12 |