ジェネリックと継承に問題があります。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
which を使用する必要があることを意味します (の特定の機能にアクセスする必要がありますMatchDay
)。私の単純な考えでは、オプション 1 と 2 は同等です。オプション 2 は、単にを実装するクラスに制限されIChromosome
たジェネリック型に置き換えます。U
IChromosome
私が達成しようとしていることは可能ですか?もしそうなら、私は何が欠けている/誤解していますか? そうでない場合、この問題にどのようにアプローチすればよいですか?
完全を期すために(質問にどれだけ役立つかわからないため、最後に含めます)、現在T
(Season
)とU
(MatchDay
)に使用している2つのエンティティを次に示します。
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; }
}
}