C# 메모리 관리 – 스태틱 함수 Static Function
C# 메모리 관리 – 스태틱 함수 Static Function
스태틱 함수 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 공간에서만 움직임이 강제됩니다.
내용 끝까지 읽어주셔서 감사합니다.
배너 클릭은 저에게 많은 힘이 됩니다.
감사합니다 🙂