문제 출처 : HOONS 닷넷 (http://www.hoons.kr/board.aspx?Name=cshaptip&BoardIdx=50598&Page=1&Mode=2)

답변 출처 : 인터넷 검색


LEVEL :: 중급


[C# 언어 부분]


난이도 ★☆☆☆☆

1. string StringBuffer의 차이점에 대해서 설명해주세요

답 : string 클래스는 변경이 불가능한 immutable 클래스이고,

        stringBuffer 클래스는 변경이 가능한 mutable 클래스이다.


- 참고: string str = "안녕";

  "안녕"이라는 문자열을 메모리에 생성하면,

 str은 "안녕"이라는 문자열 객체를 가리키는 레퍼런스를 담고 있는것이다.

우린 흔히 string문자열에 +=로 문자열을 더 추가시킨다.

str += "하세요"; 

그럼 이때 string은 불변객체 인데도 불구하고 바뀐다. 왜냐!

str += "하세요" 라는 문장은 내부적으로

str = new StringBuffer(안녕).append("하세요").toString(); 

으로 변하게 된다. String객체 자체는 불변이기 때문에 내용을 바꿀 방법이 없으므로 


1. new StringBuffer(안녕) :: "하세요" 라는 문자열 객체를 생성

2. StringBuffer 개체를 하나 생성하고, str레퍼런스가 가르키는 "안녕"으로 내용을 채운다

3. .append("하세요") :: StringBuffer 내용에 "하세요" 를 더한다.

4. StringBuffer의 내용을 문자열로 변환하고, 변환된 문자열 객체의 레퍼런스를 str에 담는다.



난이도 ★★☆☆☆

2. using 이라는 키워드는 네임스페이스를 링크하기 위해서 사용하기도 하지만 객체를 생성할 때 또한 사용되기도 합니다.

이때 using을 이용하는 목적에 대해서 설명해주세요.

- 답  : 일반적으로 객체를 생성할 경우 메모리에 데이터가 올라가고 

메모리 자원관리를 위해 객체 사용이 끝난 다음에 DIspose()를 해주어야 합니다.

using문을 사용해서 객체를 사용하면 using문의 {}를 벗어나면 객체에 관련된 자원(혹은 객체에서 사용한 자원)이

자동으로 해제되며 예외 발생시에도 자원을 해제해줍니다,.


- 참고 : IDispoable 인터페이스를 구현한 객체만 using문을 사용할 수 있습니다.



난이도 ★★★☆☆

3. C# 2.0에서는 델리게이트를 쉽게 등록하는 문법적 편의를 위해서 익명 메서드라는 문법을 제공했습니다.                    그리고 C#3.0에는 이 익명 메서드를 더 쉽게 사용할 수 있게 하기 위해서 람다식이라는 문법이 등장하게 됩니다.             그렇다면 익명메서드와 람다식 구문을 사용하는 코드를 작성해주세요.


- 답: http://tapito.tistory.com/46   <- 자세히 설명되어 있음


- 참고 : 람다 식 = 식과 문을 포함하고 대리자나 식 트리 형식을 만드는 데 사용할 수 있는 익명 함수

익명 메서드 혹은 무명 메서드 = 사용자의 입력에 따라서 method가 갖는 함수가 달라집니다.

그런데 그 함수가 클래스 상에 존재하는 함수는 아닙니다.

하나의 메서드 안에 delegate(int a, int b)로 시작해서 중괄호 안에 마치 또 하나의 함수처럼 코드블록을 가진 것이 

무명 메서드입니다.


난이도 ★★★☆☆

4. 닷넷에서의 데이터 타입은 값 타입과 참조 타입으로 구분되어 힙영역과 스택영역에 데이터를 나누어서 저장하게 됩니다때문에 빈번하게 박싱/언박싱이 일어나게 됩니다그렇다면 박싱 언박싱은 무엇인지 그리고 성능에 있어서 어떤 영향을 미치는지 설명해주세요.

- 답 : 

* 박싱 : 스택에 있는 데이터가 힙으로 복사(묵시적 & 명시적)

int = 123;

object ob = i; //박싱(묵시적 변환)

 * 언박싱 : 힙에 있는 데이터가 스택으로 복사(명시적)

int i = 123;

object ob = i;

int j = (int) ob;//언박싱(명시적 변환)

 * 성능에 미치는 영향 :

박싱 및 언박싱 과정에는 많은 처리 작업이 필요합니다.

값 형식을 박싱하는 경우 완전히 새로운 객체를 할당하고 구성해야 하며,이러한 작업에는 할당 작업보다 최대 20배의 시간 걸립니다

언박싱에 필요한 캐스팅도 상당한 계산 과정이 필요한데, 할당 작업보다 4배의 시간이 걸릴 수 있습니다.

하지만 사용상의 편의성때문에 사용하게 됩니다.


- 참고

Stack 

 ::자동 변수들이 저장되는 곳 (지역변수)

 :: LIFO(Last In First Out) = 나중에 들어간게 먼저 나온다 

Heap 

  :: 동적 메모리 할당할 경우 Heap영역에 할당 (인스턴스 변수 = 클래스내에 선언되는 변수) 

  :: FFO(First In First Out) = 먼저들어간게 먼저 나온다



/-------------------------/ 메모리상에서 | | 높은 구역 | Stack | | | /-------------------------/ | | | Heap | | | /-------------------------/ | Uninitialized data | | ---------Data---------- | | Initialized data | /-------------------------/ | | | Text | | | 메모리상에서 /-------------------------/ 낮은 구역




난이도 ★★★★☆

5. 객체를 만들 때 메모리 해제를 위해서 일반적으로 IDisposable 인터페이스를 상속받아서 처리하게 되는 경우가 많습니다닷넷에서의 소멸자는 Dispose(), Finalize()가 존재하는데 이 두 가지의 차이점은 무엇인지 기술해주세요.

- 답 : 

Dispose는 더이상 객체 사용이 불필요한 경우 명시적 제어

Finalize는 프로그래머가 Dispose 호출에 실패하는 경우 리소스가 누수되지 않도록 백업 기능 제공


- 참고 : 실행순서 Close ->Dispose ->Finalize

GC.SuppressFinalize => Dispose가 호출될 경우 더이상 Finalize가 호출될 이유가 없기 때문에 호출을 명시적으로 막는다.

* Finalize 메서드 사용 지침

  • 기본 클래스의 Finalize 메서드는 C# 및 C++ 소멸자 구문을 사용하여 자동으로 호출됩니다.
  • 종료가 필요한 개체에 대해서만 Finalize를 구. Finalize 메서드를 구현하면 성능이 저하될 수 있습니다.
  • Finalize 메서드가 필요하면 클래스 사용자가 Finalize 메서드를 호출할 필요가 없도록 IDisposable을 구현할 것인지 고려
  • Finalize 메서드를 보다가 가시적인 메서드로 만들지 않습니다. 이 메서드는 protected여야 합니다.
  • 개체의 Finalize메서드는 해당 개체가 소유하는 모든 외부 리소스를 해제해야 합니다. 또한 Finalize메서드는         
  • 해당 개체에서 보유한 리소스만 해제해야 합니다. Finalize 메서드는 다른개체를 참조하지 않습니다.
  • 해당 개체의 기본 클래스가 아닌 개체에 대해 Finalize 메서드를 직접 호출하지 않습니다.
  • 개체의 Finalize 메서드에서 기본 클래스의 Finalize 메서드를 호출합니다.

* Dispose
  • 명시적으로 해제되어야 하는 리소스를 캡슐화하는 형식에 대해 dispose 디자인 패턴을 구현합니다.                                             사용자는 공용 Dispose 메서드를 호출하여 외부 리소스를 해제할 수 있습니다.
  • 일반적으로 기본 형식에 리소스를 계속 사용하는 파생 형식이 있으면 기본 형식에서는 리소스를 계속 사용하지 않더라도 해당 기본 형식에 대해 dispose 디자인 패턴을 구현합니다. 기본 형식에 Close 메서드가 있으면 이는 대개 Dispose를 구현해야 함을 나타냅니다. 이런 경우에는 기본 형식에 대해 Finalize 메서드를 구현하지 않습니다. Finalize는 정리가 필요한 리소스를 사용하는 파생 형식에서 구현되어야 합니다.
  • 형식이 소유하는 삭제 가능한 모든 리소스는 해당 Dispose 메서드에서 해제합니다.
  • 인스턴스에 대해 Dispose를 호출한 후에는 GC.SuppressFinalize 메서드를 호출하여 Finalize 메서드가 실행되지 않도록 합니다. 드물지만Dispose에서 다루지 않는 작업을 Finalize에서 수행해야 하는 경우에는 이 규칙이 적용되지 않습니다.
  • 기본 클래스에서 IDisposable을 구현하면 기본 클래스의 Dispose 메서드를 호출합니다.
  • Dispose가 호출될 것으로 가정하지 않습니다. 형식에서 소유하는 관리되지 않는 리소스는 Dispose가 호출되지 않는 경우 Finalize 메서드에서도 해제되어야 합니다.
  • 리소스가 이미 삭제되었을 때 해당 형식(Dispose 제외)에 대한 인스턴스 메서드에서 ObjectDisposedException을 throw합니다. Dispose 메서드는 예외를 throw하지 않고 여러 번 호출할 수 있으므로 이 규칙이 적용되지 않습니다.
  • 기본 형식의 계층 구조를 통해 Dispose에 대한 호출을 전파합니다. Dispose 메서드는 해당 개체와 해당 개체 소유의 모든 개체에서 사용하는 리소스를 모두 해제해야 합니다. 예를 들어, 사용자가 모르는 사이에 TextReader에 의해 만들어지는 Stream Encoding을 계속 사용하는 TextReader 등의 개체를 만들 수 있습니다. 또한 Stream Encoding은 모두 외부 리소스를 받아 들일 수 있습니다. TextReader에 대해Dispose 메서드를 호출하면 해당 개체는 Stream Encoding에 대해 Dispose를 호출하여 해당 외부 리소스를 해제하도록 합니다.
  • Dispose 메서드가 호출된 다음에는 개체를 다시 사용할 수 없도록 하는 것이 좋습니다. 이미 삭제된 개체를 다시 만드는 것은 구현하기 어려운 패턴입니다.
  • Dispose 메서드는 예외를 throw하지 않고 한 번 이상 호출될 수 있도록 합니다. 이 메서드는 처음 호출된 이후에는 아무 작업도 수행하지 않습니다.


Posted by 퓨전마법사
,