확장 클래스 내에서 확장 메서드를 호출하는 데 '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"키워드는 매우 직관적이지 않았고 사용자는 계속해서 방법이 없다고 생각했습니다. 내가 한 일은 내 클래스를 확장 메서드를 사용하는 대신 필요한 메서드를 구현하는 부분 클래스로 만드는 것입니다. 나는 답변에서 부분적인 언급을 보지 못했습니다. 이 질문이 있으면 부분이 더 나은 옵션이 될 수 있습니다.
'Programing' 카테고리의 다른 글
Google지도 API V3에서 중심점을 오프셋하는 방법 (0) | 2020.10.21 |
---|---|
mock으로 읽기 전용 속성을 모의하는 방법은 무엇입니까? (0) | 2020.10.21 |
프로덕션 Node.js 서버 배포 (0) | 2020.10.20 |
Mockito, JUnit 및 Spring (0) | 2020.10.20 |
글꼴 (@ font-face)이 이미로드되었는지 확인하는 방법은 무엇입니까? (0) | 2020.10.20 |