2013-04-07 29 views
6

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

Phiên bản nào của.net framework bạn có sử dụng không? –

+0

.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

+0

Đ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 –

Trả lời

8

Vâng đây là vấn đề:

public IEnumerable<IChromosome> Chromosomes 

Bạn đang chỉ tuyên bố rằng bạn đang trở về một chuỗi các IChromosome giá trị. Tiêu chí của bạn mong đợi các giá trị MatchDay. Bạn xảy ra để biết rằng nó thực sự trở về một chuỗi các giá trị MatchDay, nhưng trình biên dịch thì không.

Bạn có thể sử dụng để kiểm tra Cast<> này vào thời điểm thực hiện:

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

... hoặc bạn có thể thay đổi Chromosomes để trả lại một IEnumerable<MatchDay>. Rất tiếc, chúng tôi không thể thực sự biết đó có phải là câu trả lời hợp lệ hay không vì chúng tôi không biết cách khai báo ICrossoverable. Có lẽ bạn nên tạo ICrossoverable chung trong loại phần tử?

+0

Ah ha! Điều đó xóa nó lên. Tôi nghĩ rằng giải pháp thực tế nằm trong câu cuối cùng của bạn - làm cho 'ICrossoverable' chung chung. Tôi sẽ thử vào ngày mai và báo cáo lại. – Stu

+2

Như đã đề xuất, tôi đã thực hiện 'chung chung 'có thể giải quyết được vấn đề của tôi. Mã này nằm trong [kho lưu trữ Github của tôi] (https://github.com/hungryhippo2312/GeneticAlgorithm). Tôi đổi tên thành ICrossoverable thành IOrganism vì nó phù hợp hơn với thuật ngữ thuật toán di truyền. Việc triển khai 'CriteriaBase có thể được tìm thấy [trong kho lưu trữ Github khác] (https://github.com/hungryhippo2312/FixtureGenerator/blob/master/FixtureGenerator/Criteria/SuperSundayCriteria.cs). Cảm ơn các đề xuất đa dạng và đa dạng. – Stu

3

Bạn nên sử dụng từ khóa in trước U trong định nghĩa CriteriaBase. Một cái gì đó như thế này:

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

Cập nhật. Nó sẽ không làm việc. Cố gắng xác định một cách rõ ràng gõ

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

Khi tôi làm điều này tôi nhận được một lỗi trình biên dịch nói rằng 'Biến thể loại tham số có thể được khai báo trong giao diện hoặc đại biểu chỉ'. Ba câu hỏi: những gì hiện thêm 'in' làm, những gì hiện lỗi này có nghĩa là và tại sao nó không hoạt động? Cảm ơn! – Stu

+0

Tôi quên rằng điều này có thể chỉ hoạt động cho các đại biểu và giao diện. Được. Hơn cố gắng chỉ định rõ ràng Đếm (Tiêu chí) –

+0

Bây giờ có một lỗi khác! 'Loại đối số' System.Func 'không thể gán cho kiểu tham số' System.Func '. Nó gần như là 'nơi U: IChromosome' không tồn tại! Bây giờ đang ở đâu? – Stu

Các vấn đề liên quan