2011-03-19 2 views
1

간단한 테스트에서 구조체를 메서드에 전달하면 값으로 전달되지만, 먼저 인터페이스에 할당하면 참조로 전달된다는 것을 알 수 있습니다..NET에서 구조체를 인터페이스 매개 변수가있는 메서드에 전달하면 값에 상자가 생깁니 까?

interface IFoo { int Val { get; set; } } 
struct Foo : IFoo { public int Val { get; set; } } 

void Bar(IFoo foo) { foo.Val = 1; } 

Foo foo = new Foo(); 
IFoo ifoo = new Foo(); 

Bar(foo); 
Bar(ifoo); 

Console.WriteLine(foo.Val); // 0, passed by value 
Console.WriteLine(ifoo.Val); // 1, passed by ref 

제 질문은, 이렇게 구조체를 전달하기위한 권투 작업이 아직 있습니까?

+0

참조로 전달하는 것은 해당 상황에서 혼란 스럽습니다. 가치에 의해 박스형 가치를 전달합니다. – CodesInChaos

답변

5

구조체가 인터페이스로 변환 될 때마다 boxed됩니다.

Foo foo = new Foo();//Doesn't box yet 
IFoo ifoo = new Foo();//Boxes 

Bar(foo);//creates a new boxed copy 
Bar(ifoo);//Uses the old boxed version created in line 2 

당신은 제약 조건으로 인터페이스를 사용하여 매개 변수가 일반적인함으로써 그 권투를 방지 할 수 있습니다

void Bar<T>(T foo) 
    where T:IFoo 
{ 
} 

이 제네릭은 모든 값 유형에 대한 전문 얻을 수 있다는 사실을 사용합니다.


하지만 당신은 변경할 수 strucs이 구조체는 불변하게하여 악, 그리고 그 디자인 가이드 라인을 따른다면, 그것은 코드 상자 여부별로 중요하지 경우 않습니다. 권투는 그 때 단지 경미한 성과 명중을 일으키는 원인이되고, 그러나 의미론을 많이 바꾸지 않는다.

+0

+1 : 권투를 피하고 인터페이스 제약 조건을 적용하는 방법에 관한 정보. – skjagini

0

인터페이스는 모든 참조 형식, 그래서 권투 오히려 Bar를 호출 할 때보다 라인

IFoo ifoo = new Foo(); 

에서 발생합니다.

+0

그 사건은 확실합니다. 하지만 다른 경우는 어떨까요? 메소드에 foo를 전달할 때 bar에 대한 참조가 아닌 값으로 전달됩니다. 권투는 여전히 발생합니까? –

+1

@Justin - 네,'Bar (foo)'가 호출 될 때'foo'의 boxed 복사본이 생성되어'Bar'에 전달됩니다. 왜냐하면 변경이 호출하는 메소드에 반영되지 않는 이유입니다. 'ifoo'의 경우 박스형 사본에 대한 참조 만 전달하기 때문에 변경 사항이 표시됩니다. – Lee

관련 문제