我在泛型和继承方面遇到了一些麻烦。我有一个称为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只是将IChromosome
替换为通用类型U
,该类型仅限于实现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
在元素类型中通用?