C# '无法从用法推断出类型参数'

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/15868044/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-10 18:13:08  来源:igfitidea点击:

'The type arguments cannot be inferred from the usage'

c#genericsinheritancetype-conversion

提问by Stuart Leyland-Cole

I am having some troubles with generics and inheritance. I have an abstract class called CriteriaBasewhose job it is to determine if an entity Tmatches the criteria defined in any sub-classes. The sub-classes have to implement a method which returns a Funcrepresenting the criteria. The problem arises when I try to use generics for the Func. Hopefully some code will illustrate my problem.

我在泛型和继承方面遇到了一些麻烦。我有一个抽象类CriteriaBase,它的工作是确定一个实体是否T符合任何子类中定义的标准。子类必须实现一个方法,该方法返回Func表示条件的 。当我尝试将泛型用于Func. 希望一些代码可以说明我的问题。

public abstract class CriteriaBase<T, U>
    where T : ICrossoverable
    where U : IChromosome
{
    protected abstract Func<U, bool> Criteria { get; }
    //some code removed for brevity

    private int GetNumberOfCriteriaMatches(T season)
    {
        //1.  works
        //Func<IChromosome, bool> predicate = c => c.Genes == null;
        //return season.Chromosomes.Count(predicate);

        //2.  doesn't work - The type arguments for method 'int 
        //System.Linq.Enumerable.Count<TSource>(this IEnumerable<TSource>, 
        //Func<TSource, bool>)'
        //cannot be inferred from the usage. Try specifying the type arguments 
        //explicitly.
        return season.Chromosomes.Count(Criteria);
    }
}

My intention is that the CriteriaBaseclass should be generic and completely reusable.

我的意图是CriteriaBase该类应该是通用的并且完全可重用。

An example sub-class:

一个示例子类:

public class TopTeamsPlayingEachOtherCriteria : CriteriaBase<Season, MatchDay>
{
    //some code removed for brevity

    protected override Func<MatchDay, bool> Criteria
    {
        get { return matchDay =>
            matchDay.Fixtures.Count(
                fixture =>
                fixture.HomeTeam.TableGrouping.Ordering == 1 
                && fixture.AwayTeam.TableGrouping.Ordering == 1) > 1; }
    }
}

The problem is in the GetNumberOfCriteriaMatches()method. Option 2 is how I originally wrote the code but I get the compile error as listed. If I use option 1 then the code compiles but it means that when I override Criteriain the sub-class, I have to use IChromosomeinstead of MatchDaywhich doesn't work (I need to access specific features of a MatchDay). In my simple mind, options 1 and 2 are equivalent. Option 2 simply replaces IChromosomewith a generic type Uwhich is restricted to a class that implements IChromosome.

问题出在GetNumberOfCriteriaMatches()方法上。选项 2 是我最初编写代码的方式,但我得到了列出的编译错误。如果我使用选项 1,那么代码会编译,但这意味着当我Criteria在子类中覆盖时,我必须使用IChromosome而不是MatchDay哪个不起作用(我需要访问 a 的特定功能MatchDay)。在我看来,选项 1 和选项 2 是等效的。选项 2 只是替换IChromosome为泛型类型U,该类型仅限于实现IChromosome.

Is what I'm trying to achieve possible? If so, what am I missing/misunderstanding? If not, how should I approach this problem?

我正在努力实现的目标是可能的吗?如果是这样,我错过了什么/误解了什么?如果没有,我应该如何解决这个问题?

For completeness (included at the end as I'm not sure how much it helps with the question), here are the two entities that I'm currently using for T(Season) and U(MatchDay).

为了完整性(包括在最后,因为我不确定它对问题有多大帮助),这里是我目前用于T( Season) 和U( MatchDay)的两个实体。

public class Season : ICrossoverable
{
    private readonly IEnumerable<MatchDay> _matchDays;

    public Season(IEnumerable<MatchDay> matchDays)
    {
        _matchDays = matchDays;
    }

    public IEnumerable<MatchDay> MatchDays
    {
        get { return _matchDays; }
    }

    //ICrossoverable implementation
    public IEnumerable<IChromosome> Chromosomes
    {
        get { return _matchDays; }
    }
}

public class MatchDay : IChromosome
{
    private readonly int _week;
    private readonly List<Fixture> _fixtures;

    public MatchDay(int week, List<Fixture> fixtures)
    {
        _week = week;
        _fixtures = fixtures;
    }

    //some code removed for brevity

    public IEnumerable<Fixture> Fixtures
    {
        get { return _fixtures; }
    }

    //IChromosome implementation
    public IEnumerable<IGene> Genes
    {
        get { return Fixtures; }
    }
}

采纳答案by Jon Skeet

Well this is the problem:

嗯,这就是问题所在:

public IEnumerable<IChromosome> Chromosomes

You're onlydeclaring that you're returning a sequence of IChromosomevalues. Your criterion expects MatchDayvalues. Youhappen to know that it's actually returning a sequence of MatchDayvalues, but the compiler doesn't.

只是声明您正在返回一系列IChromosome值。您的标准MatchDay期望值。碰巧知道它实际上返回了一个MatchDay值序列,但编译器没有。

You could use Cast<>to check this at execution time:

您可以使用Cast<>在执行时检查这一点:

return season.Chromosomes.Cast<U>().Count(Criteria);

... or you could change Chromosomesto return an IEnumerable<MatchDay>. Unfortunately we can't really tell whether that's a valid answer or not as we don't know how ICrossoverableis declared. Perhaps you should make ICrossoverablegeneric in the element type?

...或者您可以更改Chromosomes为返回一个IEnumerable<MatchDay>. 不幸的是,我们无法真正判断这是否是有效答案,因为我们不知道如何ICrossoverable声明。也许您应该ICrossoverable在元素类型中使用泛型?

回答by Kirill Bestemyanov

You should use keyword inbefore U in CriteriaBase definition. Something like this:

您应该in在 CriteriaBase 定义中的 U 之前使用关键字。像这样的东西:

public abstract class CriteriaBase<T, in U>
    where T : ICrossoverable
    where U : IChromosome

Update. It will not work. Try to specify type explicitly

更新。不起作用。尝试明确指定类型

private int GetNumberOfCriteriaMatches(T season)
{
 ....
    return season.Chromosomes.Count<IChromosome>(Criteria);
}