본문 바로가기
C#/Effective C#

[Effective C#] Item15 불필요한 객체를 만들지 마라

by 코모's 2022. 7. 13.
반응형
  • 모든 참조 타입의 객체는 지역 변수라도 동적으로 메모리를 할당하는데 일허게 할당된 객체는 이 객체를 참조하는 상위 멤버가 삭제되면 가비지가 된다.
  • 힙에서 새로운 객체를 생성하고 삭제하는 작업은 생각보다 많은 프로세서시간을 사용하기때문에 성능에 문제를 초래할 수 있다.

 

  • 참조 타입의 지역변수를 멤버변수로 선언
    • 자주 호출되는 이벤트 핸들러에 참조 타입의 객체를 지역변수로 선언하면 가비지 콜렉터가 많은 생성/ 제거를 반복하여 성능에 문제가 발생한다.
public class FirstControl : Control
{
	public FirstControl() {}
    protected override void OnPaint(PaintEventArgs e)
    {
    	//나쁜 예, Point 이벤트가 발생할 때 마다 동일한 폰트를 생성한다.
        using(Font MyFont = new Font("Arial", 10.0f))
        {
        	e.Graphics.DrawString(DateTiem.Now.ToString(), MyFont,
            Brushed.Black, new PointF(0,0));
        }
        
        base.OnPaint(e);
    }
}
  • OnPaint는 동일한 Font객체를 매번 다시 생성합니다. [MyFont]
  • 생성/제거를 자주 반복하면 사용되는 메모리 양이 많아져서 매우 비효율적인 코드가 된다.
  • Font 객체를 지역변수가 아닌 멤버변수로 변경하여 폰트 객체를 한번만 생성한 후 이를 재상요 하도록 한다.
public Class SecondControl : Control
{
	public SecondControl(){}
    
    //멤버변수
    public Font MyFont {get; private set;}
    
    protected override void OnPaint(PaintEventArgs e)
    {
    	e.Graphics.DrawString(DateTime.Now.ToString(), MyFont,
        Brusheds.Black, new PointF(0,0));
        
        base.OnPaint(0);
    }
}

 

  • 종속성 삽입을 황요하여 자주 사용되는 객체를 정적 멤버 변수로 선언하여 재사용
private static Brush blackBrush;
public static Brush Black
{
	get
    {
    	if(blackBrush == null)
        {
        	blackBrush =new SolidBrush(Color.Black);
        }
        
        return blackBrush;
    }
}
  • Black을 최초로 요청했을때 객체를 생성
  • 생성된 객체를 저장해두고 호출할때마다 해당 객체를 돌려줌
  • But, 경우에 따라 생성된 객체가 사용되지 않는데도 메모리에 오래 남아 있을 수 있다는 단점이 있음
  • 또한, Dispose() 메서드를 호출해야 할 시점을 결정할 수 없기 때문에 비관리 리소스를 삭제할 수 없다는 것도 큰 단점

 

  • Immutagle(변경불가) 타입을 주의
pbulci void TestString()
{
	stirng msg = "Hello, ";
    msg += "Hi!";
    msg += ". Today is ";
    msg += System.DateTime.Now.ToString();
}

해당 코드 작업은 string 객체 msg에 새로운 문자열을 더하는것이 아니라 완전히 새로운 string 객체를 생성해서 반환

string msg = string.Format("Hello, {0}. Today is {1}", thisUser.Name, DateTime.No.ToString());

이처럼 문자열 보간을 사용해서 코드를 작성하는것이 좋다.

publci void TestStringBuilderExample()
{
	StringBuilder sb = new StringBuilder("ABC", 50);
    sb.Append(new char[] { 'D', 'E', 'F'});
    sb.AppendFormat("GHI{0{{1}", 'J', 'k');
    sb.Insert(0, "Alphabet: ");
    sb.Replace('k','K');
}

만약 위처럼 문자열 만드는 방식이 복잡한 경우라면 StringBuilder 클래스를 사용하는것이 좋습니다.

반응형