2010-04-11 2 views
21

Extension Methodref 수정 자로 호출하는 것이 금지 된 이유는 무엇입니까?확장 메서드에서 처음 ("this") 매개 변수에 대해 ref 및 out을 사용할 수 없습니까?

이 일이 가능합니다 :

public static void Change(ref TestClass testClass, TestClass testClass2) 
{ 
    testClass = testClass2; 
} 

그리고이 아니다 :

public static void ChangeWithExtensionMethod(this ref TestClass testClass, TestClass testClass2) 
{ 
    testClass = testClass2; 
} 

왜?

+1

확실한'ref'가 필요합니까? 나는 그것이 "this"에 의해 "자동 생성"될 것이라고 기대할 것이다 - 비표준 확장 메소드는 의미가 없다. –

+0

그러나 내가 실수하지 않으면 그들은 참조가 아닙니다. – Hun1Ahpu

+0

@MarcelJackwerth ref 매개 변수는 참조 유형 매개 변수와 다릅니다. ref 매개 변수는 호출자의 참조 (또는 포인터) 자체를 전달합니다. ref를 사용하면 다른 객체를 가리 키도록 참조를 업데이트 할 수 있습니다. 이를 사용하지 않으면 (참조 유형의 경우) 객체 자체는 업데이트 할 수 있지만 참조는 참조 할 수 없습니다. – xr280xr

답변

19

명시 적으로 refout을 지정해야합니다. 확장 방법 으로 어떻게 처리 하시겠습니까? 게다가 정말로 을 원하시는 분은에?

TestClass x = new TestClass(); 
(ref x).ChangeWithExtensionMethod(otherTestClass); 
// And now x has changed? 

또는 당신이 원하는 것은 확장 메서드의 첫 번째 매개 변수를 들어, ref 부분을 지정할 필요가 없습니다합니까?

솔직히 말해서 나에게 이상하게 들리고, 읽을 수없는 (또는 적어도 예측하기 힘든) 코드의 제조법에 불과합니다.

+2

하지만 그 이유는 더 이상 C# 4에 적용되지 않습니다. 사실, 올바르게 기억하면 VB에서는 * By * 확장 메서드를 사용할 수 있습니다. –

+3

"지정해야합니다 ... 명시 적으로"인공 컴파일러 요구 사항은 여기에 드롭 할 수 있습니다. 그것은 그것을 훨씬 더 모호하게 만들 것이다. –

+0

@ Konrad : C# 4에서는 COM 메소드에만 적용되지 않습니다. @ en크 : 그렇습니다, 그것은 '인공적'입니다 - 그러나 가독성을 위해서. 나는 이것이 완전히 합당한 제한이라고 생각한다. –

1

이렇게하면 myObject.ChangeWithExtentionMethod(otherObject)을 호출하면 실제로 myObject의 값이 변경 될 수 있습니다. IMO는 ref가있는 일반 비 확장 방법을 사용하여 원하는 효과를 얻을 수있을 때 매우 판독 가능한 코드를 만들지 않습니다.

편집 : 요점은 메서드 호출은 참조로 무언가를 전달할 때마다 ref 키워드를 사용해야한다는 것입니다. 확장 메서드의 'this'매개 변수로 ref를 사용하면 해당 동작을 위반하게됩니다.

4

나는 Jon Skeet 외의 답변에 동의한다. "ref this"확장 메서드를 사용하면 코드가 더 모호해질 수 있습니다. 그러나 .Net Framework에서 일부 네임 스페이스를 살펴보면 구조체에서 호출되는 메서드에서 해당 메서드를 변경하는 것이 일반적입니다.

예를 들어 System.Drawing 구조체 (Point, Rectangle 등)를 사용하십시오. 각 메소드에는 구조체 자체를 변경하는 메소드 (예 : 오프셋, 팽창 등)가 있습니다. 나는 이것이 좋은 생각이라는 것을 말하지 않고있다. 사실 개인적으로 Offset, Inflate 등이 구조체 자체를 돌연변이시키는 것을 매우 짜증나게한다. 나는 여러분 중 일부가 가변 구조체의 아이디어에 반대한다. 일반.

레퍼런스 유형의 메소드를 호출하면 레퍼런스가 변경되는 경우가 의심 스럽습니다 (String 클래스가 아닌 한, 인터뷰 수행을위한 참조를 전환하는 일부 컴파일러 마법이 있다고 생각할 수 있습니다). 따라서 참조를 변경하는 것이 메서드 호출의 완전히 비표준적인 부작용이 될 수 있으므로 "this ref"가 참조 형식과 함께 사용되는 것을 방지하는 것이 좋습니다.

구조체와 관련하여 "this ref"를 사용하면 코드 가독성이 Rectangle.Inflate 등보다 크게 감소하지 않으며 확장 기능을 사용하여 그러한 종류의 동작을 "시뮬레이트"하는 유일한 방법을 제공합니다.그냥 사이드 참고로

, 여기에 "이 심판" 유용 할 수 있습니다, 여전히 읽을 이럴 하나의 예입니다

void SwapWith<T>(this ref T x, ref T y) { 
    T tmp = x; x = y; y = tmp; 
} 
3

가 동의 그래서 유용한 구조체

에 대한

그 구조체 확장 메서드를 만들기 위해 제안하고 싶습니다. 이 키워드는 항상 참조로 struct를 전달해야합니다.

클래스는 항상 참조로 전달됩니다. 그리고 우리가 확장 메서드를 만들 때마다 실제 메서드처럼 동작하기를 원합니다. 그래서 클래스와 구조체의 실제 메소드는 그 값을 수정할 수 있습니다. 확장 메서드도 가능해야합니다

관련 문제