본문 바로가기
개발/Unity

유니티 C# - 확장 메서드 (Extension Method) / static method 의 this parameter

by 피로물든딸기 2022. 5. 30.
반응형

Unity 전체 링크

 

C#에는 확장 메서드(Extension Method) 기능을 지원한다.

미리 정의된 형식에 사용자 정의 함수를 추가할 수 있다.

 

MyMath.cs를 만들고 아래와 같이 작성한다.

이때 static class인 MyMath의 static 메서드에서 parameter에 this가 있는 MySquared확장 메서드가 된다.

using System;

public static class MyMath
{
    /* 확장 메서드 */
    public static int MySquared(this int value)
    {
        return value * value;
    }

    /* 정적 메서드 */
    public static float MySafeDivide(float value, float divider)
    {
        if (divider == 0) return 0;
        return value / divider;
    }
}

 

확장 메서드는 정적 클래스(static class)에서만 선언가능하다.


Ctrl + Shift + N으로 빈 오브젝트를 만든 후, TestEvent.cs를 추가하자.

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class TestEvent : MonoBehaviour
{
    void Start()
    {
        float val1 = 5.0f;
        float ret1 = MyMath.MySafeDivide(val1, 5);

        Debug.Log("ret1 : " + ret1);

        int val2 = 3;
        int ret2 = val2.MySquared();
    }
}

 

실행 결과는 아래와 같다.

 

정적 메서드 MySafeDivide를 사용하기 위해 MyMath에 . 을 붙인 후 메서드를 호출한다.

MyMath.MySafeDivide(val1, 5);

 

그러나 확장 메서드정적 메서드와 사용 방법이 다르다.

this int value에 의해 int 변수 다음에 MySquared를 호출할 수 있게 되었다.

    public static int MySquared(this int value)
    {
        return value * value;
    }

 

따라서 아래와 같이 사용 가능하다.

val2.MySquared();

 

심지어 단순한 상수에서도 호출해도 문제가 없다. (Debug.Log로 값을 찍어보면 9가 나온다.)

3.MySquared(); // 9

 

원한다면 정적 메서드처럼 쓰는 것도 가능하다. 

이 경우에는 MyMath를 불러주고, 알맞은 parameter를 넘겨줘야 한다.

//int ret2 = val2.MySquared();
int ret2 = MyMath.MySquared(val2);

확장 메서드는 보통 namespace로 관리하여 사용한다.

위의 경우는 namespace가 없기 때문에 모든 스크립트에서 호출되므로 관리하기가 힘들 수 있다.

아래와 같이 MyMath.cs를 수정하자. MyExtensionMethod라는 이름의 namespace 안에 선언하였다.

using System;

namespace MyExtensionMethod
{
    public static class MyMath
    {
        /* 확장 메서드 */
        public static int MySquared(this int value)
        {
            return value * value;
        }

        /* 정적 메서드 */
        public static float MySafeDivide(float value, float divider)
        {
            if (divider == 0) return 0;
            return value / divider;
        }
    }
}

 

이제 TestEvent.cs에 using MyExtensionMethod; 을 추가한 스크립트에서만 확장 메서드를 호출할 수 있다.

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using MyExtensionMethod;

public class TestEvent : MonoBehaviour
{
    void Start()
    {
        float val1 = 5.0f;
        float ret1 = MyMath.MySafeDivide(val1, 5);

        Debug.Log("ret1 : " + ret1);

        int val2 = 3;
        //int ret2 = MyMath.MySquared(val2);
        int ret2 = val2.MySquared();

        Debug.Log("ret2 : " + ret2);
    }
}

이제 testObject라는 게임 오브젝트에

type이 1이면 BoxCollider를 추가하고, type이 2면 Rigidbody를 추가한다고 가정해보자.

type이 늘어나면 else if가 계속 늘어나게 된다.

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using MyExtensionMethod;

public class TestEvent : MonoBehaviour
{
    public GameObject testObject;

    void Start()
    {
        int type = 1;

        if (type == 1) testObject.AddComponent<BoxCollider>();
        else if (type == 2) testObject.AddComponent<Rigidbody>();
        //else if (...)
    }
}

 

그리고 여러 스크립트에서 이러한 Component를 추가하는 코드가 있다면,

요구사항이 추가될 경우, 모든 스크립트에 else if를 수정해야 하는 불편함이 있다.

 

이러한 문제점은 확장 메서드를 이용해서 아래와 같이 단 한줄로 해결할 수 있다.

testObject.MyAddComponent((MyEnum)type);

 

MyMath.cs에서 아래와 같이 확장메서드를 만들었다. (이름과 달리 수학과 관련된 메서드는 아니지만...)

    public enum MyEnum { Nothing, MyBoxCollider, MyRigidbody }

    public static class MyComponent
    {
        public static void MyAddComponent(this GameObject go, MyEnum type)
        {
            if (type == MyEnum.MyBoxCollider) go.AddComponent<BoxCollider>();
            else if (type == MyEnum.MyRigidbody) go.AddComponent<Rigidbody>();
        }
    }

 

이제 확장 메서드 MyAddComponent에 else if만 추가해주면 다른 스크립트에서는 수정을 할 필요가 없어진다.

 

빈 오브젝트를 만들어서 TestEvent에 추가한 후, 동적으로 Rigidbody나 BoxCollider가 잘 추가 되는지 확인해보자.

 

아래는 TestEvent에 연결된 TestObject이다.

type == 1인 경우 BoxCollider가 동적으로 생성된 것을 알 수 있다.

 

최종 코드는 아래와 같다.

 

MyMath.cs

using System;
using UnityEngine;

namespace MyExtensionMethod
{
    public enum MyEnum { Nothing, MyBoxCollider, MyRigidbody }

    public static class MyComponent
    {
        public static void MyAddComponent(this GameObject go, MyEnum type)
        {
            if (type == MyEnum.MyBoxCollider) go.AddComponent<BoxCollider>();
            else if (type == MyEnum.MyRigidbody) go.AddComponent<Rigidbody>();
        }
    }

    public static class MyMath
    {
        /* 확장 메서드 */
        public static int MySquared(this int value)
        {
            return value * value;
        }

        /* 정적 메서드 */
        public static float MySafeDivide(float value, float divider)
        {
            if (divider == 0) return 0;
            return value / divider;
        }
    }
}

 

TestEvent.cs (1)

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using MyExtensionMethod;

public class TestEvent : MonoBehaviour
{
    void Start()
    {
        float val1 = 5.0f;
        float ret1 = MyMath.MySafeDivide(val1, 5);

        Debug.Log("ret1 : " + ret1);

        int val2 = 3;
        //int ret2 = MyMath.MySquared(val2);
        int ret2 = val2.MySquared();

        Debug.Log("ret2 : " + ret2);
    }
}

 

TestEvent.cs (2)

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using MyExtensionMethod;

public class TestEvent : MonoBehaviour
{
    public GameObject testObject;

    void Start()
    {
        int type = 1;

        testObject.MyAddComponent((MyEnum)type);
    }
}

 

Unity Plus:

 

Easy 2D, 3D, VR, & AR software for cross-platform development of games and mobile apps. - Unity Store

Have a 2D, 3D, VR, or AR project that needs cross-platform functionality? We can help. Take a look at the easy-to-use Unity Plus real-time dev platform!

store.unity.com

 

Unity Pro:

 

Unity Pro

The complete solutions for professionals to create and operate.

unity.com

 

Unity 프리미엄 학습:

 

Unity Learn

Advance your Unity skills with live sessions and over 750 hours of on-demand learning content designed for creators at every skill level.

unity.com

반응형

댓글