C# 메모리 관리 – 스태틱 함수 Static Function

C# 메모리 관리 – 스태틱 함수 Static Function

memory management

 

스태틱 함수 Static Function

스태틱 함수는 논-스태틱 클래스 에서도 구현 가능한데, 이 경우 그 클래스의 스태틱 멤버들만 스태틱 함수에서 접근이 가능합니다. 스태틱 함수는 인스턴스가 아닌 클래스를 통해서 호출이 되기 때문에 스태틱 멤버에만 접근 가능한 것은 매우 논리적이라고 할 수 있습니다. 또한, 존재 여부가 불 확실한 멤버에 접근하는 것은 문제의 소지가 많습니다.

반면에 파라미터를 전달하는 것은 가능하고 아마 이런 종류의 함수를 꾀 많이 사용해 오고 계실겁니다.

Vector3.Distance(vec1, vec2);
vec1.Normalize();
 
Application.LoadLevel(1);
 
if (GUI.Button(Rect(10, 10, 50, 50), btnTexture)) { }

이런 식의 함수 사용은 굉장히 빈번합니다. 두 번째 줄 예제는 스태틱 메소드가 아닙니다. Normalize() 함수는 Vector3 타입의 vec1 인스턴스를 통해서 호출되었습니다. 나머지 예제들은 스태틱 함수를 호출하기 위해서 사용되는 클래스의 예를 보여주고 있습니다.

스태틱 함수는 논-스태틱 함수보다 다소 빠른 경향을 보이는데, 인스턴스 함수를 호출하면 그 인스턴스가 존재하는 지 여부를 확인하기 위한 과정이 필요하지만, 스태틱 함수는 존재가 보장되어 있는 클래스를 사용하기 때문에 확인 과정이 필요없습니다. 하지만 이 시간은 매우 짧기 때문에 크게 고려할 필요는 없습니다.

스태틱 클래스의 다른 이점으로, 스태틱 클래스는 프로그램이 실행되는 동안에 계속 존재하기 때문에 C#에서는 확장 메소드 extention method에 사용될 수 있습니다 – 확장 메소드는 다른 변수 타입에 추가할 수 있는 함수를 말합니다.

이 기능을 이용해서 확장된 클래스는 실제로 열리지 않지만(이 클래스의 private과 protected 변수들은 확장 메소드에서 사용 불가능합니다), 이 방법이 이미 존재하는 객체에 함수를 추가하는 깔끔하고 분명한 방법이며, 이를 통해서 읽기 쉽고 사용하기 쉬운 API를 만드는 데 도움이 될 수 있습니다.

예를 들어, 확장 메소드를 통해서 transform.MyWeirdNewFunction(x); 와 같은 함수를 추가할 수 있습니다.

 

확장 함수 사용 예:

배열에 사용될 함수를 추가해서 기존에 이미 존재하는 기능을 확장 시키고 싶다고 가정해보겠습니다(OrderBy, Sort 등등). 이 경우, 스태틱 함수를 선언해서 기능을 확장할 수 있습니다.

using UnityEngine;
using System.Collections;
 
public static class ExtensionTest
{
 
    public static int BiggestOfAll(this int[] integer)
    {
        int length = integer.Length;
        int biggest = integer[0];
        for(int i = 1; i < length; ++i) { if(integer[i] > biggest)
                biggest = integer[i];
        }

        return biggest;
    }
}

예제에서 스태틱 함수를 선언하고, 파라미터가 전달되는 과정을 잘 살펴보시기 바랍니다. 파라미터의 타입을 변경하면 다른 객체에서도 사용이 가능합니다.

이제 배열을 선언하고 배열을 데이터로 채웠습니다:

using UnityEngine;
using System.Collections;
 
public class Test : MonoBehaviour
{
 
    private int[] array = {1,25,12,120,12,6};
    private void Start ()
    {
        print(array.BiggestOfAll()); 
    }
}

배열이름 뒤에 점(.)을 입력하면 새로 선언한 함수가 나타나는 것을 확인할 수 있습니다.

타입에 관계없이 모든 배열에서 사용할 수 있는 제네릭 함수를 만들고 싶은 경우, 스태틱 제네릭 확장 메소드를 구현하면 됩니다.

using UnityEngine;
using System.Collections;
using System.Collections.Generic;
 
public static class ExtensionTest
{
    public static T TypelessBiggestOfAll<T>(this T[] t)
    {
        int length = t.Length;
        var biggest = t[0];
        for(int i = 1;i < length;i++)
        {
            biggest =((Comparer<T>.Default.Compare(t[i], biggest) > 0) ? t[i] : biggest);
        }

        return biggest;
    }
}

예제 코드 상단에 using System.Collections.Generic;가 추가된 것을 볼 수 있습니다. 컴파일러가 T의 타입을 모르기 때문에, < 또는 > 연산자를 이용해서 비교할 수 없지만, Comparer<T>를 사용해서 비교할 수 있습니다.

예제에서는 삼항 연산자가 사용되었는데, 처음보면 혼동될 수 있지만 잘 활용하면 코드 라인을 줄일 수 있습니다.

이제 이를 활용해서 다른 타입의 배열을 선언해서 같은 함수를 사용할 수 있습니다.

using UnityEngine;
using System.Collections;
 
public class Test : MonoBehaviour
{
    private int[] arrayInt = {1, 25, 12, 120, 12, 6};
    private float[] arrayFl = {0.5f, 52.456f, 654.25f, 41.2f};
    private double[]arrayDb = {0.1254, -15487.258, 654, 8795.25, -2};
 
    private void Start()
    {
         print(arrayInt.TypelessBiggestOfAll());
         print (arrayFl.TypelessBiggestOfAll());    
         print (arrayDb.TypelessBiggestOfAll());
    }
}

이 예제는 결과로 120, 654.25, 8795.25를 출력합니다.

이제 확장 메소드가 어떤 상황에서 유용한 지 살펴보겠습니다.
많은 유니티 사용자들이 어떤 오브젝트를 특정 지역 안에서만 움직이도록 하는 기능에 대해서 질문합니다.
예를 들어 오브젝트를 화면 안에서만 움직이도록 제한 하려는 경우, 이 함수를 이용해서 해당 오브젝트의 Transform을 고정할 수 있습니다.

using UnityEngine;
using System.Collections;
 
public static class GameManager
{
    public static void ClampTransform(this Transform tr,Vector3 move, Vector3 min, Vector3 max)
    {
        Vector3 pos = tr.position + move;
        if(pos.x < min.x ) pos.x = min.x; else if(pos.x > max.x)
            pos.x = max.x;
 
        if(pos.y  < min.y ) pos.y = min.y; else if(pos.y > max.y)
            pos.y = max.y;
 
        if(pos.z < min.z) pos.z = min.z; else if(pos.z > max.z)
            pos.z = max.z;
 
        tr.position = pos;
    }
}

이제 필요할 때 아래 예제와 같은 방식으로 사용하면 됩니다.

Vector3 minVector = new Vector3(-10,0,-10);
Vector3 maxVector = new Vector3(10,0,10);
transform.ClampTransform(move,minVector,maxVector);

이 예제에서, 이 오브젝트는 원점이 (0,0,0)이고 20 x 20 크기의 정사각형 2D 공간에서만 움직임이 강제됩니다.

 

내용 끝까지 읽어주셔서 감사합니다.

배너 클릭은 저에게 많은 힘이 됩니다.

감사합니다 🙂

RonnieJ

프리랜서 IT강사로 활동하고 있습니다. 게임 개발, 웹 개발, 1인 기업, 독서, 책쓰기에 관심이 많습니다.

댓글 남기기

이메일은 공개되지 않습니다. 필수 입력창은 * 로 표시되어 있습니다