연장 클래스 내에서 확장 방법을 호출하기 위해“this”를 사용해야하는 이유는 무엇입니까?

StackOverflow https://stackoverflow.com/questions/1616294

  •  06-07-2019
  •  | 
  •  

문제

나는 수십 개의 확장 방법을 작성했으며 모두 예상대로 작동합니다. 그러나이 맥락에서 확장 방법을 사용하는 것은 이번이 처음입니다.

public static class ControllerExtensions
{
    public static RedirectToRouteResult RedirectToAction<TController>(
        this Controller controller
        , Expression<Action<TController>> action
      ) where TController : Controller
    {
      RouteValueDictionary routeValuesFromExpression = 
        ExpressionHelper.GetRouteValuesFromExpression<TController>(action);

      return new RedirectToRouteResult(routeValuesFromExpression);
    }
}

충분히 정상적으로 보입니다. 그러나 컨트롤러 내에서 입력 하여이 확장 방법에 액세스 할 수 없습니다. 대신 키워드 "this"로 접두사해야합니다. 예를 들어:

// This does not work, I get a compiler error because
// RedirectToAction has no overload for the generic.
//
return
  RedirectToAction<MembershipController>(
     c => c.RegisterSuccess(Server.UrlEncode(code) ));

// But, this does work?!?!
//
return
  this.RedirectToAction<MembershipController>(
     c => c.RegisterSuccess(Server.UrlEncode(code) ));

매우 이상합니다. 아마도 내가 확장중인 인스턴스 객체 안에 있기 때문일 것입니까? "컨트롤러"인스턴스는?

물론 간단한 콘솔 앱에서 복제 할 수있었습니다.

class Program
{
    static void Main(string[] args)
    {
        var x = new TestClass();
        x.Go<String>();
    }
}

public class TestClass
{
    public void Go()
    {
    }

    public void NextMethod()
    {
        // compiler error.  :(
        Go<String>();

        // works!
        this.Go<String>();
    }
}

public static class TestExtension
{
    public static string Go<T>(this TestClass theClass)
    {
        return String.Empty;
    }
}

그래서 왜 '이것'이라요. 일하다?

도움이 되었습니까?

해결책

확장 방법은 멤버의 "기본"조회의 일부가 아닙니다. 양식의 표현식을 사용해야합니다. Target.Method 확장 방법을 확인하기 전에. this.Foo() 해당 요구 사항을 준수하므로 작동합니다.

섹션 7.5.5.2에서 :

양식 중 하나의 메소드 호출 (§7.5.5.1)에서

expr . identifier ( )
expr . identifier ( args )
expr . identifier < typeargs > ( )
expr . identifier < typeargs > ( args ) if the normal processing of the

호출은 적용 가능한 방법을 찾지 못하고 확장 방법 호출로 구성을 처리하려는 시도가 이루어집니다.

분명히 말하는 것은 사양이 그런 식으로 작성된 이유보다는 "컴파일러가 사양을 따릅니다"라는 것입니다 ... 나는 거기에 있는지 모르겠습니다. ~이다 특정 이유, 두 인스턴스 멤버를 모두 호출 할 수 있다는 사실. 그리고 정적을 사용하는 정적 회원 Method() (인스턴스 또는 유형을 지정하는 대신) 관련이있을 수 있습니다.

다른 팁

나는 확장 방법이 어떻게 작동하는지 때문이라고 생각합니다.

go ()를 쓸 때 컴파일러는 GO가 현재 클래스의 메소드라고 가정합니다.

확장 메소드는 인스턴스에 '첨부'되며이 키워드를 사용하여 인스턴스를 지정합니다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top