Tôi đang gặp một số rắc rối với generics và inheritance. Tôi có một lớp trừu tượng được gọi là CriteriaBase
có công việc là xác định xem một thực thể T
có khớp với các tiêu chí được xác định trong bất kỳ lớp con nào không. Các lớp con phải triển khai phương thức trả về một số Func
đại diện cho tiêu chí. Vấn đề nảy sinh khi tôi cố gắng sử dụng Generics cho Func
. Hy vọng rằng một số mã sẽ minh họa cho vấn đề của tôi.'Các đối số kiểu không thể suy ra từ việc sử dụng'
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);
}
}
Mục đích của tôi là lớp CriteriaBase
phải chung chung và có thể sử dụng lại hoàn toàn.
Một ví dụ 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; }
}
}
Vấn đề là trong phương pháp GetNumberOfCriteriaMatches()
. Tùy chọn 2 là cách tôi đã viết mã ban đầu nhưng tôi nhận được lỗi biên dịch như được liệt kê. Nếu tôi sử dụng tùy chọn 1 thì mã biên dịch nhưng có nghĩa là khi tôi ghi đè Criteria
trong phân lớp, tôi phải sử dụng IChromosome
thay vì MatchDay
không hoạt động (tôi cần truy cập các tính năng cụ thể của MatchDay
). Trong suy nghĩ đơn giản của tôi, các tùy chọn 1 và 2 là tương đương. Tùy chọn 2 chỉ đơn giản là thay thế IChromosome
bằng loại chung U
được giới hạn cho một lớp thực hiện IChromosome
.
Tôi đang cố gắng đạt được điều gì? Nếu vậy, tôi đang thiếu gì/hiểu nhầm? Nếu không, tôi nên tiếp cận vấn đề này như thế nào?
Để hoàn chỉnh (bao gồm ở cuối như tôi không chắc chắn có bao nhiêu nó giúp với các câu hỏi), sau đây là hai thực thể mà tôi hiện đang sử dụng cho T
(Season
) và 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; }
}
}
Phiên bản nào của.net framework bạn có sử dụng không? –
.NET phiên bản 4 - phiên bản đầy đủ không phải là hồ sơ khách hàng. Câu trả lời có khác nhau tùy theo phiên bản không? Sử dụng Visual Studio 2010 nếu điều đó thú vị. – Stu
Đoàn kết hiệp phương sai và contravariance đang làm việc trong C# từ phiên bản 4.0 –