无法将匿名方法块转换为委托,因为块中的某些返回类型不可隐式转换

问题描述 投票:0回答:1

我想重构一些异步创建 ViewModel 的函数。他们看起来如下:

public async Task NavigateToCreateFormVM()
{
    try
    {
        IsLoading = true;
        CurrentVM = await Task.Run(() => new CreateFormVM());
        <...>
        IsLoading = false;
    }
    catch (Exception ex)
    {
        MessageBox.Show(ex.Message, "App", MessageBoxButton.OK, MessageBoxImage.Error);
    }
}

所以为了重构所有逻辑,我尝试编写一个委托来保持代码易于维护。

public async Task NavigationDelegate(Func<Task<BaseVM>> delegate)
{
    try
    {
        IsLoading = true;
        CurrentVM = await delegate();
        <...>
        IsLoading = false;
    }
    catch (Exception ex)
    {
        MessageBox.Show(ex.Message, "App", MessageBoxButton.OK, MessageBoxImage.Error);
    }
}

例如将我的功能更改为:

public async Task NavigateToCreateFormVM()
{
    await NavigationDelegate(() => Task.Run(() => new CreateFormVM()));
}

public async Task NavigateToConsultFormVM()
{
    await NavigationDelegate(() => ConsultFormVM.CreateAsync()); // type of ConsultFormVM
}

但是我收到两条错误消息,表明它们无法将 CreateFormVM/ConsultFormVM 转换为 BaseVM(它们都来自 BaseVM)。如果我将

NavigationDelegate(Func<Task<BaseVM>> delegate)
更改为
NavigationDelegate(Func<Task<CreateFormVM>> delegate)
它可以正常工作。

错误消息为 CS0029 和 CS1662。

无法将类型“System.Threading.Tasks.Task”隐式转换为“System.Threading.Tasks.Task” 无法将匿名方法块转换为委托类型,因为块中的某些返回类型不能隐式转换为委托返回类型

我不知道我是否遗漏了某些东西,或者我是否做错了什么(或者根本不应该这样做?),所以如果有人知道如何解决我的问题,我将不胜感激。

c# async-await func
1个回答
0
投票

Func<T>
的类型参数不是逆变的,
Task<T>
的类型参数不是协变的。所以你不能做这些:

    public class Base
    {
    }

    public class Derived : Base
    {
    }

    public static void Main()
    {
        Func<Task<Base>> d = GetBase;
        Func<Task<Derived>> e = d; // Will fail
        Task<Base> dd = GetDerived(); // Will fail
    }

    public static Task<Base> GetBase()
    {
        return Task.FromResult(new Base());
    }

    public static Task<Derived> GetDerived()
    {
        return Task.FromResult(new Derived());
    }

小提琴

© www.soinside.com 2019 - 2024. All rights reserved.