泛型和扩展方法——智能感知如何推断类型

本文关键字:何推断 类型 感知 智能 扩展 方法 泛型 | 更新日期: 2023-09-27 18:08:32

我有一个关于编译器在使用泛型和扩展方法时如何推断类型的问题。问我的问题最简单的方法是先展示一些代码…

我有一个ViewModelBase类看起来有点像这样(所有不相关的东西都拿出来了)。基本上我的NavigationService类在每次应用程序转到它所链接的视图时都会调用navigingto方法。

该类的继承者可以调用Return委托将数据传递给调用者。

public abstract class ViewModelBase<TContext, TReturn>
{
    public Action<TReturn> Return { get; set; }
    public abstract void NavigatingTo(TContext context);
}

然后我有一个继承ViewModelBase的测试ViewModel:

public class TestViewModel : ViewModelBase<int, bool>
{
    public override void NavigatingTo(int context)
    {
        // do stuff here
    }
}

接下来,我有一个通用的NavigationCommand类,它接受ViewModelBase,如下所示:

public class NavigationCommand<TViewModel>
{
    public TViewModel ViewModel { get; set; }
    public NavigationCommand(TViewModel viewModel)
    {
        this.ViewModel = viewModel;
    }
}

最后,我有一个扩展方法为NavigationCommand类添加一个导航方法。我在这里的目的是,通过声明我的导航方法需要一个带有TContext和TReturn的ViewModelBase,编译器应该能够推断出实际要使用的类型:

public static class NavigationExtensions
{
    // I actually pass in a INavigationService here too, but I have left that out to
    // make it easier to read...
    public static void Navigate<TViewModel, TContext, TReturn>(
        this NavigationCommand2<TViewModel> viewModel, 
        TContext context, 
        Action<TReturn> returnAction) 
        where TViewModel : ViewModelBase<TContext, TReturn>
    {
        // actual implementation omitted
    }
}

好的,现在在我的ApplicationController类中我做了下面的操作:

var vm = new TestViewModel();
var cmd = new NavigationCommand2<TestViewModel>(vm);
int clientID = 1;
Action<bool> returnAction = success =>
{
    Console.WriteLine(success.ToString());
};
cmd.Navigate(clientID, returnAction);

它可以工作,如果你试图传递一个不正确的类型,你会在构建时得到一个编译器错误。但是,智能感知不会提示您输入正确的类型。

所以我的问题:有没有办法重写扩展方法,或我的NavigationCommand类或ViewModel等,以便智能感知实际上提示我使用正确的类型?

目前所有的智能感知给我的是这个:

(extension void) NavigateCommand<TestViewModel>.Navigate(TContext context, Action<TReturn> returnAction)

当我想要的是:

(extension void) NavigateCommand<TestViewModel>.Navigate(int context, Action<bool> returnAction)

泛型和扩展方法——智能感知如何推断类型

解决这个问题的方法之一是将TContext和TReturn类型参数传播到NavigationCommand,因此它的声明看起来像:

public class NavigationCommand<TViewModel, TContext, TReturn> where TViewModel:ViewModelBase<TContext, TReturn>

但是它使命令初始化更加冗长(因为TestViewModel类型实际上已经包含了关于TContextTReturn实际类型的信息):

var cmd = new NavigationCommand<TestViewModel, int, bool>(vm);

实际上,您发布的实现已经是类型安全的,并且不允许您传递不正确类型的参数(让我们说string而不是int)。唯一的问题是智能感知由于某种原因不能正确推断类型