성능을 중요시 하는 프로그램을 만들 때(특히 Unity를 사용한 게임) GC를 조심해야 하므로 불필요한 new를 사용하지 않아야 한다.

그러니 일부 눈에 보이는 코드에는 new를 사용하지 않지만 내부에서 사용되는 경우가 있다.

 

1. 박싱화

var x = (object)10;

 

void Test(object o)

{

}

 

Test(10);

 

 

2. 제너릭을 사용할 때 Object를 사용하는 메소드 사용

bool IsSame<T>(T t1, T t2)

{

    return t1.Equals(t2);

}

위의 IsSame은 제너릭 함수라서 박싱화가 일어나지 않을 것이라고 생각하지만 Equals 메소드가 Object를 사용해서 박싱화가 일어난다.

public virtual bool Equals(Object obj);

 

이 문제를 회피하기 위해서는 아래처럼 사용해야 한다.

public interface IEquatable<T>

{

    bool Equals(T other);

}

 

bool IsSame<T>(T t1, T t2) where T : IEquatable<T>

{

    return t1.Equals(t2);

}

 

혹은

bool IsSame<T>(T t1, T t2)

{

    return EqualityComparer<T>.Default.Equals(t1, t2);

}

 

 

3. 람다식의 보이지 않는 new

static int DoubleStatic(int x)

{

    return x * 2;

}

 

int DoubleInstance(int x)

{

    return x * 2;

}

 

void Run()

{

    var two = int.Parse("2");

 

    Enumerable.Range(1, 1).Select(DoubleStatic);           // 1

    Enumerable.Range(1, 2).Select(DoubleInstance);         // 2

    Enumerable.Range(1, 3).Select(x => x * 2);             // 3

    Enumerable.Range(1, 4).Select(x => x * two);           // 4

    Enumerable.Range(1, 5).Select(x => DoubleStatic(x));   // 5

    Enumerable.Range(1, 6).Select(x => DoubleInstance(x)); // 6

}

 

패턴 1, 2는 메소드를 직접 넣은 경우로 델리게이트를 사용하므로 new를 사용한다.

패턴 3은 일반적으로 자주 사용하는 패턴으로 new를 사용하지 않는다.

패턴 4도 자주 사용되는 패턴으로 로컬 변수를 사용해서 클래스가 만들어지므로 new를 사용한다.

패턴 5static 메소드를 사용해서 첫 호출 이외에는 캐시된 것을 사용하므로 별 문제 되지 않는다.

패턴 6은 델리게이트를 사용하므로 new를 사용한다.

 

위의 코드의 안 보이는 코드를 표현하면 아래와 비슷해진다.

static Func<int, int> cacheA;

static Func<int, int> cacheB;

 

internal static int LambdaA(int x)

{

           return x * 2;

}

 

class Closure

{

    internal int two;

 

    internal int LambdaB(int x)

    {

        return x * two;

    }

}

 

internal static int LambdaC(int x)

{

           return DoubleStatic(x);

}

 

internal static int LambdaD(int x)

{

           return DoubleInstance(x);

}

 

void Run()

{

    var two = int.Parse("2");

 

    // 1 - Select(DoubleStatic)

    Enumerable.Range(1, 1).Select(new Func<int, int>(DoubleStatic));

 

    // 2 - Select(DoubleInstance)

    Enumerable.Range(1, 2).Select(new Func<int, int>(DoubleInstance));

 

    // 3 - Select(x => x * 2)

    if(cacheA != null)

    {

        cacheA = new Func<int, int>(LambdaA);

    }

    Enumerable.Range(1, 3).Select(cacheA);

 

    // 4 - Select(x => x * two)

    var closure = new Closure();

    closure.two = two;

    Enumerable.Range(1, 4).Select(new Func<int, int>(closure.LambdaB));

 

    // 5 - Select(x => DoubleStatic(x))

    if(cacheB != null)

    {

        cacheB = new Func<int, int>(LambdaC);

    }

    Enumerable.Range(1, 5).Select(cacheB);

 

    // 6 - Select(x => DoubleInstance(x))

    Enumerable.Range(1, 6).Select(new Func<int, int>(LambdaD));

}

 

 

 

출처: http://neue.cc/2016/01/06_525.html

 

저작자 표시
신고
by 흥배 2016.02.03 07:52