박싱과 언박싱을 최소화하라
.NetFramework 환경에서는 모든 타입을 참조타입인 System.Object로 정의한다.
위와 같은 정의방식으로 우리는 서로 다른 타입을 이어준다.
박싱 : 생성한 인스턴스를 상위 클래스나 인터페이스에 포함시키는 작업
언박싱 : 박싱으로 인해 상위 클래스 내부에서 포함되어있는 인스턴스의 복사본을 가져오는 작업
int i = 25;
object o = i; //박싱
int z = o as int; //언박싱
정말 쉬운 예제이다.
나같은 초보 개발자들은 코딩을 하다보면 해당 상황과 비슷한 상황에 직면하면
구현이 최우선인지라 신경쓰지 않고 코딩부터 한다.
최근에는 같은 기능을 하는 Class 2개에서 메서드 1개씩만 각각 가져와서 사용하는 상황이 있었다.
interface iMethod
{
void Function();
}
class FunctionalClass1 : iMethod
{
public void Function(){...}
}
class FunctionalClass2 : i Method
{
public void Function(){...}
}
class HandlerClass
{
public List<iMethod> Methods
{
get
{
return new List<iMethod>(){new FunctionClass1(), new FunctionClass2};
}
}
}
일단 잘됐다!
하지만 위와같이 사용하면 FunctionClass1~2를 iMethod라는 인터페이스로 박싱을 시켜버려
성능을 하향시킨다...
그러면 어떻게 해야 할까?
지금 떠오르는 방법은 Strategy pattern이다!!
interface iMethod
{
void Function();
}
class MethodBehavior1 : iMethod
{
public void Function(){...}
}
class MethodBehavior2 : iMethod
{
public void Function(){...}
}
class FunctionalClass1
{
private iMethod _method = new MethodBehavior1();
public iMethod Method
{
get
{
return _method;
}
}
}
class FunctionalClass2
{
private iMethod _method = new MethodBehavior2();
public iMethod Method
{
get
{
return _method;
}
}
public FunctionalClass2(iMethod method)
{
this._method = method;
}
}
class HandlerClass
{
FunctionalClass1 _functionclass1 = new FunctionalClass1();
FunctionalClass2 _functionclass2 = new FunctionalClass2();
public List<iMethod> Methods
{
get
{
return new List<iMethod>(){_functionclass1.Method, _functionclass2.Method};
}
}
}
막상 구현해보니 BehaviorClass는 결국 인터페이스로 박싱을 한다...
하지만 이전 HandlerClass에서 Methods를 Get을 여러번하면 여러번 박싱 했지만
이제는 한번만 한다. 별로 만족스럽지 못한 결과다...
Effective C#에서 보여준 예제로 마지막을 깔끔하게 정리해야겠다..
int nFirstNumber = 1;
int nSecondNumber = 2;
//박싱을 무시한 예시
Console.WriteLine($@"Number1 {nFirstNumber}, Number2 {nSecondNumber}")
//위의 동작은
//int i = 1;
//object o = i;
//string output = o.toString();
//와 같은 원리로 동작한다고한다..
//박싱을 최소화한 예시
Console.WriteLine($@"Number1 {nFirstNumber.toString()}, Number2 {nSecondNumber.toString()}")
//위의 동작은 object로 변하는 박싱동작을 피하고 바로 string으로 넘겨준다고한다.
//string output = nFirstNumber.toString();
결론
System.Object 타입이나 인터페이스 타입으로 변경하는 코드는 가능한 작성하지 말아야한다.
하지만 코드의 유지보수성과 코웍이 가능한 코드도 중요하다!
CLR 만세!
'Program > Effective C#' 카테고리의 다른 글
Effective C# ITEM14 (0) | 2020.10.28 |
---|---|
Effective C# ITEM13 (0) | 2020.10.28 |
Effective C# ITEM 12 (0) | 2020.10.26 |
Effective C# ITEM11 (0) | 2020.10.25 |
Effective C# ITEM10 (0) | 2020.10.21 |