有时通用类型推断不起作用。为什么会这样?

时间:2018-02-02 09:16:14

标签: c# .net generics type-inference

我在C#中使用自定义扩展方法:

IF([formula]=0,"",1)

正如您可能猜到的,这种方法是一个稍微调整过的版本:

//version 1
public static IEnumerable<TSource> ForEachAndReturnSelf<TSource>(this IEnumerable<TSource> container, System.Action<TSource> delegateAction)
{ 
    foreach (var v in container) delegateAction(v); return container; 
} 

唯一不同的是我的方法返回自己(不是void):

无论如何,该方法的版本工作正常 但我有这个方法的新版本返回原始类型而不是System.Collections.Generic.List<T>.ForEach() 所以我把方法改为:

IEnumerable<TSource>

因为我需要像这样使用它:

//version 2
public static T ForEachAndReturnSelf<T,TSource>(this T container, System.Action<TSource> delegateAction) where T : IEnumerable<TSource>
{ 
    foreach (var v in container) delegateAction(v); return container; 
} 

但是当我将版本1更改为2时,使用此方法的代码的所有部分现在都会产生编译器错误:

  

方法的类型参数   无法从使用情况中推断出//Example Usage1 List<int> list = /* initialize */; list.ForEachAndReturnSelf(_ => _ *= 2).Convert(_ => _.ToString()).Sort(); //Example Usage2 list.ForEachAndReturnSelf(_ => _ *= 2)[0] = 4; 。尝试   明确指定类型参数

问题是:
我认为提供的类型信息足以推断出类型,但为什么不能呢? 我如何满足提供类型知识,以便我可以返回与提供的原始类型相同的类型?

2 个答案:

答案 0 :(得分:2)

首先,你的方法签名只有一个通用参数需要两个,所以看起来应该是这样的

 public static TCollection ForEachAndReturn<TCollection,TItem>(this TCollection Container, Action<TItem> action)
        where TCollection : IEnumerable<TItem>
    {
        foreach (var item in Container)
        {
            action(item);
        }
        return Container;
    }

现在您仍然会收到您提到的编译器警告。这是因为可以推断您的收藏类型。但是,你是通用约束,说TCollection必须是IEnumberable<TSource>类型,只能用于提供有关TCollection的信息。这就是为什么你需要告诉编译器TSource的类型。通用约束就是这样,它们用于约束,你不能从你正在约束的东西推断约束的类型,我想这可能会导致问题。因此,为什么无法从TCollection提供的泛型参数推断出TSource。

我希望这是有道理的。

编辑:错过了一点对不起,所以要摆脱编译器警告,你得到的只是需要提供类型信息。

var myList = new List<string>();

list.ForEachAndReturn<List<string>,string>(i => //do stuff);

答案 1 :(得分:0)

因此,首先,您只需要一个通用参数,而您需要其中的两个。将您的方法定义更改为:

public static TCollection ForEachAndReturnSelf<TCollection, TItem>(this TCollection container, System.Action<TItem> delegateAction) where TCollection : IEnumerable<TItem>

现在要使用它,您必须包含您用来调用此方法的泛型类型:

meList.ForEachAndReturnSelf<List<int>, int>(i => ... );

Try this online