为何Controller中调用扩展方法GetUserId()必须加this才能被识别?
问题背景
我有一个继承自ControllerBase的UserController:
public class UserController : ControllerBase
其中包含一个PUT方法:
[HttpPut] [Authorize] public async Task<bool> PutUser([FromBody] UserDetailsDto user) { if (!_userService.CheckIfRequesterAsksForOwnDetails(user.Id!, GetUserId())) return false; return await _userService.UpdateExistingUserAsync(user); }
GetUserId()是定义在独立类中的扩展方法:
public static class ControllerExtensions { public static string GetUserId(this ControllerBase controller) { var userId = controller.User.FindFirst(ClaimTypes.NameIdentifier)?.Value; if (userId is null) throw new ArgumentNullException("UserId is missing in Claims!"); return userId; } }
在控制器方法中直接写GetUserId()时方法不可见,必须加上this.写成this.GetUserId()才能被识别,请问这是为什么?
原因解析
这是C#扩展方法的调用规则导致的:
- 扩展方法本质是静态方法,它的第一个参数用
this修饰,用来指定该方法扩展的类型(这里是ControllerBase)。 - 在类的实例方法内部调用扩展方法时,编译器不会自动把当前类的实例(也就是
UserController的实例,它继承自ControllerBase)作为第一个参数传递给扩展方法。 - 只有通过
this.显式调用时,编译器才能识别出这是在调用扩展方法,自动把当前实例作为第一个参数传入扩展方法的controller参数中,从而正确找到这个方法。
简单来说,扩展方法需要一个目标实例,this在这里就是明确告诉编译器:用当前控制器实例作为扩展方法的目标对象,这样才能匹配到定义的GetUserId扩展方法。
内容的提问来源于stack exchange,提问作者Val
相关产品推荐
相关产品推荐

