Programing

확장 클래스 내에서 확장 메서드를 호출하는 데 'this'키워드가 필요한 이유

lottogame 2020. 10. 20. 07:15
반응형

확장 클래스 내에서 확장 메서드를 호출하는 데 'this'키워드가 필요한 이유


ASP.NET MVC ViewPage에 대한 확장 메서드를 만들었습니다. 예 :

public static class ViewExtensions
{
    public static string Method<T>(this ViewPage<T> page) where T : class
    {
        return "something";
    }
}

View에서이 메서드를 호출 할 때 (에서 파생 됨 ViewPage) 키워드를 사용하여 호출 하지 않으면 " CS0103 : The name 'Method'is not exist in the current context " 오류가 발생 this합니다.

<%: Method() %> <!-- gives error CS0103 -->
<%: this.Method() %> <!-- works -->

this키워드가 필요한 이유는 무엇 입니까? 아니면 그것 없이도 작동하지만 뭔가 빠졌나요?

(이 질문의 중복이있는 것 같지만 찾을 수 없습니다)

업데이트 :

벤 로빈슨은 말한다 , 전화 번호 방법에 대한 구문은 컴파일러 설탕이다. 그렇다면 컴파일러가 this 키워드없이 현재 유형의 기본 유형의 확장 메서드를 자동으로 확인할 수없는 이유는 무엇입니까?


몇 가지 요점 :

첫째, 제안 된 기능 (확장 메서드 호출에서 암시 적 "this.")이 필요하지 않습니다 . LINQ 쿼리 이해가 우리가 원하는 방식으로 작동하려면 확장 메서드가 필요했습니다. 수신자는 항상 쿼리에 명시되어 있으므로 LINQ가 작동하도록 암시 적으로이를 지원할 필요가 없습니다.

둘째,이 기능 은 확장 메서드의보다 일반적인 디자인에 대해 작동 합니다. 즉, 확장 메서드를 사용하면 인터페이스이고 구현을 알지 못하기 때문에 확장 할 수없는 유형을 확장 할 수 있습니다. 구현을 알고 있지만 소스 코드가 없습니다.

해당 유형 내의 유형에 대해 확장 메소드를 사용하는 시나리오에있는 경우 소스 코드에 액세스 있습니다. 그렇다면 처음에 확장 방법을 사용하는 이유는 무엇입니까? 확장 된 유형의 소스 코드에 액세스 할 수있는 경우 인스턴스 메소드를 직접 작성할 수 있으며 확장 메소드를 전혀 사용할 필요가 없습니다! 그러면 구현에서 확장 메서드가 할 수없는 개체의 개인 상태에 액세스 할 수 있습니다.

액세스 권한이있는 유형 내에서 확장 메서드를 사용하기 쉽게 만드는 것은 인스턴스 메서드보다 확장 메서드를 사용하도록 장려하는 것입니다. 확장 메서드는 훌륭하지만 일반적으로 인스턴스 메서드가있는 경우 사용하는 것이 좋습니다.

이 두 가지 점을 감안할 때 더 이상 기능이 존재 하지 않는 이유를 설명하기 위해 언어 디자이너가 부담하지 않습니다 . 이제 이유를 설명 할 일인 해야한다 . 기능에는 이와 관련된 막대한 비용이 있습니다. 이 기능은 필요하지 않으며 확장 방법의 명시된 설계 목표에 위배됩니다. 구현 비용을 부담해야하는 이유는 무엇입니까? 이 기능을 통해 어떤 매력적이고 중요한 시나리오를 사용할 수 있는지 설명하고 향후 구현을 고려할 것입니다. 나는 그것을 정당화하는 설득력 있고 중요한 시나리오를 보지 못했지만 아마도 내가 놓친 시나리오가있을 것입니다.


이것이 없으면 컴파일러는 페이지를 첫 번째 매개 변수로 사용하는 정적 클래스의 정적 메서드로 간주합니다.

// without 'this'
string s = ViewExtensions.Method(page);

// with 'this'
string s = page.Method();

인스턴스 메서드에서 'this'는 암시 적으로 각 메서드에 투명하게 전달되므로 제공하는 모든 멤버에 액세스 할 수 있습니다.

확장 메서드는 정적입니다. 또는 Method()대신 호출 하면 컴파일러에게 메서드에 전달할 내용을 알리지 않습니다.this.Method()Method(this)

당신은 '왜 호출하는 객체가 무엇인지 깨닫고 그것을 매개 변수로 전달하지 않는가?'라고 말할 수 있습니다.

대답은 확장 메서드가 정적이며 'this'가없는 정적 컨텍스트에서 호출 할 수 있다는 것입니다.

나는 그들이 컴파일하는 동안 그것을 확인할 수 있다고 생각하지만, 솔직히 말해서, 그것은 아마도 극히 적은 보상으로 많은 작업 일 것입니다. 솔직히 말해서 확장 메서드 호출의 명시 성을 제거하는 데 따른 이점은 거의 없습니다. 인스턴스 메서드로 착각 할 수 있다는 사실은 때때로 매우 직관적이지 않을 수 있음을 의미합니다 (예를 들어 NullReferenceExceptions는 throw되지 않음). 나는 때때로 그들이 확장 메소드를위한 새로운 '파이프 포워드'스타일 연산자를 도입 했어야한다고 생각합니다.


확장 방법과 일반 방법간에 차이있다는 점에 유의하는 것이 중요 합니다. 나는 당신이 그들 중 하나를 방금 본 것 같습니다.

다른 차이점의 예를 들어 보겠습니다 null. 객체 참조 에서 확장 메서드를 호출하는 것은 매우 쉽습니다 . 다행히도 이것은 일반적인 방법으로 수행하기가 훨씬 더 어렵습니다. (하지만 할 수 있습니다. IIRC, Jon Skeet은 CIL 코드를 조작하여이를 수행하는 방법을 시연했습니다.)

static void ExtensionMethod(this object obj) { ... }

object nullObj = null;
nullObj.ExtensionMethod();  // will succeed without a NullReferenceException!

this, 확장 메서드를 호출하는 데 필요한 것이 조금 비논리적으로 보인다는 데 동의합니다 . 결국 확장 방법은 이상적으로는 "느낌"을 가져야하며 일반적인 방법과 똑같이 작동해야합니다.

그러나 실제로 확장 방법은 모든 측면에서 언어에 잘 맞는 초기 핵심 기능보다 기존 언어 위에 추가 된 구문 설탕과 비슷합니다.


ViewPage 클래스에는 확장 메서드가 없기 때문입니다. 확장 메서드를 호출하는 내용을 컴파일러에 알려야합니다. .NET this.Method()용 컴파일러 설탕을 기억하십시오 ViewExtensions.Method(this). 메서드 이름으로 클래스 중간에있는 확장 메서드를 호출 할 수없는 것과 같은 방식입니다.


나는 유창한 API를 작업 중이며 동일한 문제가 발생했습니다. 확장중인 클래스에 액세스 할 수 있지만 각 유창한 메서드의 논리가 자체 파일에 있기를 원했습니다. "this"키워드는 매우 직관적이지 않았고 사용자는 계속해서 방법이 없다고 생각했습니다. 내가 한 일은 내 클래스를 확장 메서드를 사용하는 대신 필요한 메서드를 구현하는 부분 클래스로 만드는 것입니다. 나는 답변에서 부분적인 언급을 보지 못했습니다. 이 질문이 있으면 부분이 더 나은 옵션이 될 수 있습니다.

참고URL : https://stackoverflow.com/questions/3510964/why-is-the-this-keyword-required-to-call-an-extension-method-from-within-the-e

반응형