编程语言
首页 > 编程语言> > c# – 使用泛型类型参数时模糊方法重载

c# – 使用泛型类型参数时模糊方法重载

作者:互联网

考虑以下程序:

using System;
using System.Threading.Tasks;

public class Program
{
    public static void Main()
    {
        var stringTask = Task.FromResult("sample");
        stringTask.TeeAsync(st => Task.CompletedTask).Wait();
    }
}

public static class FunctionalExtensions
{
    public static async Task<T> TeeAsync<T>(this T source, Func<T, Task> asyncAction)
    {       
        await Task.Delay(0); // todo: do something with source

        return source;
    }

    public static async Task<T> TeeAsync<T>(this Task<T> asyncSource, Func<T, Task> asyncAction)
    {
        var source = await asyncSource;

        await Task.Delay(0); // todo: do something with source

        return source;
    }
}

第9行上的编译器错误,其中在stringTask上调用TeeAsync,因为

The call is ambiguous between the following methods or properties: ‘FunctionalExtensions.TeeAsync<T>(T, Func<T, Task>)’ and ‘FunctionalExtensions.TeeAsync<T>(Task<T>, Func<T, Task>)’

从每个过载中移除第二参数突然允许编译器区分Task< T>.和T表示第一个参数.但是为什么第二个参数 – 两个重载之间相同 – 会导致编译器混淆?

解决方法:

第二个参数不相同.它们都是Func< T,Task>,但在每种情况下T都不同.

第一次重载有这个T源.这意味着当你这样做

Task<string> stringTask = Task.FromResult("sample");
stringTask.TeeAsync(...)

对于第一次重载,T是Task< string>.

第二个具有该任务< T> asyncSource.所以在上面的情况下,对于第二个过载,T是字符串.

因为您没有在此处指定st的类型:

stringTask.TeeAsync(st => Task.CompletedTask).Wait();

st可以是Task< string> (第一次重载)或字符串(第二次).编译器无法知道你的意思.如果你这样做:

stringTask.TeeAsync((string st) => Task.CompletedTask).Wait();

它会正确选择第二个.如果你这样做

stringTask.TeeAsync((Task<string> st) => Task.CompletedTask).Wait();

它会先选择.

有趣的是,如果您实际使用st的方式将允许编译器推断它是否是字符串或任务< string> – 它会那样做.例如,这将编译并选择第二个重载:

// we don't specify st type, but using Length property
// which only exists on string
stringTask.TeeAsync(st => Task.FromResult(st.Length)).Wait();

这将首先编译并选择:

// we don't specify st type, but using Result property
// which only exists on Task<string>
stringTask.TeeAsync(st => Task.FromResult(st.Result)).Wait();

但是如果你使用两者都存在的东西,它将再次(正确地)无法选择过载:

// ToString() exists on both string and Task<string>
// so doesn't help compiler to choose
stringTask.TeeAsync(st => Task.FromResult(st.ToString())).Wait();

标签:c,net,overload-resolution,generics
来源: https://codeday.me/bug/20190522/1153053.html