2009-12-22 4 views
12

그래서 나는 권투와 언 박싱이 무엇인지 이해합니다. 실제 코드에서 어떤 것이 나타나거나 어떤 예제에서 문제가 발생합니까?권투 및 언 박싱 : 언제 시작됩니까?

int i = 123; 
object o = i;   // Boxing 
int j = (int)o;  // Unboxing 

을 ...하지만 그건 거의 확실 매우 과도하게 단순화 그리고 난 전에 그것을 모른 채 복싱/언 박싱을했을 수도 있습니다 :이 예제와 같이 일을 상상할 수 없다.

+0

나는 동의합니다. 내가 주제에 관해 읽었던 모든 것에서 나는 단지 요점을 얻지 못한다. 뭔가 빠져 있어야합니다 :) –

답변

31

그것은 제네릭 이전보다 지금 문제의 많은 덜합니다. 이제 예를 들어 다음을 사용할 수 있습니다.

List<int> x = new List<int>(); 
x.Add(10); 
int y = x[0]; 

전혀 복싱 또는 복싱이 필요하지 않습니다.

이전에, 우리가 있었다 것 :

ArrayList x = new ArrayList(); 
x.Add(10); // Boxing 
int y = (int) x[0]; // Unboxing 

것을 권투와 언 박싱 내 가장 일반적인 경험, 적어도. 제네릭이 관여하지 않고

, 난 아마 그 반사 I가 작업 한 프로젝트에서 복싱의 가장 흔한 원인이다라고 말하고 싶지만 생각합니다. 리플렉션 API는 메소드의 반환 값과 같은 객체에 대해 항상 "객체"를 사용합니다. 그 이유는 무엇을 사용해야할지 모르기 때문입니다. 당신이 인터페이스를 구현하는 값 형식을 사용하고 매개 변수로 인터페이스 유형이 다른 방법으로 그 값을 전달하면 당신이 그것을 인식하지 않으면 당신을 잡을 수

또 다른 원인이다. 다시 말하지만, 제네릭을 사용하면이 문제가 줄어들지 만 인식하지 못하면 놀랄 수 있습니다.

+7

"아마도 나는 반성이 내가해온 프로젝트에서 권투의 가장 보편적 인 원인이라고 말할 것"이라고 생각합니다. 물론 이것은 프로젝트의 종류에 크게 의존 할 것입니다. 예를 들어, WPF 또는 Silverlight로 작업하는 경우 값 변환기 (IValueConverter는 객체를 가져오고 반환 함)로 작업 할 때마다 boxing이 * 항상 발생합니다. 종속성 속성 (DependencyObject.GetValue 및 SetValue 반환 및 가져 오기 객체) 등 – itowlson

+0

+1 값 유형에 구현 된 인터페이스의 경우 - 부적절한 경우 –

+0

@itowlson : 위의 예입니다. 내 대답에 추가하면 되겠습니까? –

8

권투 (내 경험) 보통 이러한 경우에 발생합니다

  • 값 유형은 유형 Object의 인수를 허용하는 방법에 전달됩니다.
  • 값 유형이 ArrayList과 같이 비 일반 콜렉션에 추가됩니다.

.NET Framework의 리플렉션 API가 리플렉션을 사용할 때 복싱과 언 박싱을 볼 수있는 다른 경우는 Object을 많이 사용합니다.

+1

참고 : int (Int32)는 Object 클래스의 하위 클래스 인 ValueType 추상 클래스의 하위 클래스입니다. –

+0

나는 그것이 "하위 클래스"라고 말하지 않을 것입니다 - 클래스 *가 아닙니다. 'ValueType'을 상속 (또는 파생)합니다. C# 및 CLI 스펙은이 앞면에서 약간 다른 용어를 사용합니다. –

1

권투 언 박싱 정말 유형을 참조하는 값 형식에서 움직이고있다. 스택에서 힙으로 이동하고 다시 이동하는 것으로 생각하십시오.

확실히 관련성이있는 경우가 있습니다. 2.0 프레임 워크에 제네릭을 포함 시키면 많은 일반적인 권투 사례가 실제로 작동하지 않게되었습니다.

+0

C# 2가 아니라 2.0 프레임 워크;) – disklosr

0

C# 2.0 (Visual Studio 2005)과 함께 제네릭을 사용하는 강력한 형식의 목록 및 사전이 등장한 이래로 나는 boxing/unboxing을 염두에두고 유지하는 것이 중요하다고 생각합니다. 해당 nullable 형식 (int?, 등) 및 null 병합 연산자 (??)를 사용하여 추가하고 정말 많이 걱정하지 않아야하며 가능성이없는 Framework 1.1 또는 이전 버전의 모든 코드에서 볼 수 있습니다.

+2

아니요, 제네릭에는 대부분의 사람들이 기대하는 것보다 훨씬 많은 권투가 진행되고 있습니다. unconstraint Ts를 null과 비교할 때 C#이 .box를 방출합니다. –

+0

그 점에 동의합니다 -하지만 일반적인 방법/클래스를 구현할 때 개발자가 결정해야합니다. 프레임 워크 관점에서 볼 때 일반 콜렉션은 소비자가 boxing/unboxing 시나리오를 포기하도록 허용합니다. 내가 설명하는 시나리오를 코딩 할 때, 제약되지 않은 T는 null이 아닌 기본값 (T)과 비교 될 것입니다. 만약 내가 * 정말로 * null에 대한 검사가 필요하다면, T는 참조 형에 제약을받는 것이 더 좋다. –

+0

"1.1 Framework 이전 버전이 아닌 코드에서"- 간단한 문자열은 무엇입니까? 형식 ("내 번호는 {0}", 123)? – Alex

4

복식/언 박싱은 object과 같은 참조 유형을 허용하는 값 ​​유형 (예 : struct, int, long)이 전달 될 때 발생합니다.

값 형식을 전달할 개체 형식의 매개 변수를 사용하는 메서드를 명시 적으로 만들 때 발생합니다. 또한 이전의 비 제네릭 컬렉션을 사용하여 값 유형 (일반적으로 프리미티브)을 저장할 때도 나타납니다.

String.Format()을 사용하고 기본 요소를 전달할 때 복싱이 표시됩니다. String.Format()은 params 객체 []를 허용하기 때문에 호출에 추가 매개 변수가 복싱됩니다. 반사 API를 선택의 여지가 없기 때문에 실제 유형이 컴파일시에 알려지지 않은 (그리고 반사 API를 일반 수 없습니다) 이후 object을 반환하지만 또한 권투/unboxing을 초래할 수있는 방법을 호출 반사를 사용

.

새로운 일반 콜렉션은 boxing/unboxing을하지 않으므로 ArrayList, Hashtable 등과 같이 이전 콜렉션보다 더 좋습니다. 그들은 타입 안전합니다.

개체를 받아들이는 메서드를 변경하여 복싱 문제를 피할 수 있습니다.

public void string Decorate(object a) // passing a value type results in boxing 
{ 
    return a.ToString() + " Some other value"; 
} 

대 : 예를 들어

public void string Decorate<T>(T a) 
{ 
    return a.ToString() + " some other value"; 
} 
1

그것은 사람들이 의미가 무엇인지 모르는 모든 시간을 발생, 단순히 상관 없어 때로는 하나는 도움이되지만 덜으로 권투를 받아 들일 수 없다 evel.

value-type 속성에 액세스 할 때 강력하게 형식화 된 datarows는 box/unbox와 거의 항상 일치합니다. 또한 인터페이스 참조로 값 유형을 사용하면 상자에 표시됩니다. 또는 값 형식의 인스턴스 메서드에서 대리자를 가져 오는 중입니다. :) 여기

3

정말 불쾌한 일이다 (대리인의 목표는 Object 유형이다)이 가능하지 않은 UINT32에 Int32 형식을 언 박싱하려고하기 때문에

SqlCommand cmd = <a command that returns a scalar value stored as int>; 

// This code works very well. 
int result = (int)cmd.ExecuteScalar(); 

// This code will throw an exception. 
uint result = (uint)cmd.ExecuteScalar(); 

(가) 두 번째 실행이 실패합니다. 따라서 첫 번째와 두 번째 캐스팅을 해제해야합니다.

uint result = (uint)(int)cmd.ExecuteScalar(); 
+0

+1 예를 제공합니다 – chikak

관련 문제