类型参数不能从用法'推断出来

本文关键字:推断出 不能 用法 类型参数 | 更新日期: 2023-09-27 18:07:51

我在泛型和继承方面遇到了一些麻烦。我有一个称为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);
    }
}

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

子类示例:

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; }
    }
}

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

我想要达到的是可能的吗?如果是这样,我遗漏了什么?如果不是,我该如何处理这个问题?

为了完整性(包括在最后,因为我不确定它对问题有多大帮助),这里是我目前用于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; }
    }
}

类型参数不能从用法'推断出来

问题就在这里:

public IEnumerable<IChromosome> Chromosomes

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

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

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

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

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

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

。这是行不通的。尝试显式指定类型

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