2017-06-11 3 views
2

Ich habe Klassen, die Schnittstellen von Klassen implementieren, die von einer gemeinsamen Basis abgeleitet sind. Gibt es eine Möglichkeit, diese zu kombinieren, um mit ihnen als Set zu arbeiten?Schnittstellen von abgeleiteten Klassen kämmen

Ich erkunde Co und Kontravarianz, aber ohne Erfolg.

Danke für Ihre Hilfe.

void Main() 
{ 
    var textAnswers = new IAnswerValidator<TextQuestion, TextAnswer>[] { new NoDogsValidator(), new MaxLengthValidator() }; 
    var dateAnswers = new IAnswerValidator<DateQuestion, DateAnswer>[] { new NotChristmasDayValidator() }; 

    // Can I combine into a list or enumerable? 
    // var allValidators = new List<IAnswerValidator<QuestionBase, AnswerBase>>(); 
    // allValidators.AddRange(textAnswers); 
    // allValidators.AddRange(dateAnswers); 


    // The goal is to be able to combine so as to be able to work on them as a set. 
} 

public class ValidationResult { } 

public class AnswerBase { } 
public class TextAnswer : AnswerBase { } 
public class DateAnswer : AnswerBase { } 

public class QuestionBase { } 
public class TextQuestion : QuestionBase { } 
public class DateQuestion : QuestionBase { } 

public interface IAnswerValidator<TQuestion, TAnswer> where TQuestion : QuestionBase, new() where TAnswer : AnswerBase, new() 
{ 
    ValidationResult Validate(TQuestion question, TAnswer answer); 
} 

public class NoDogsValidator : IAnswerValidator<TextQuestion, TextAnswer> 
{ 
    public ValidationResult Validate(TextQuestion question, TextAnswer answer) { return new ValidationResult(); } // simplified 
} 

public class MaxLengthValidator : IAnswerValidator<TextQuestion, TextAnswer> 
{ 
    public ValidationResult Validate(TextQuestion question, TextAnswer answer) { return new ValidationResult(); } // simplified 
} 

public class NotChristmasDayValidator : IAnswerValidator<DateQuestion, DateAnswer> 
{ 
    public ValidationResult Validate(DateQuestion question, DateAnswer answer) { return new ValidationResult(); } // simplified 
} 

Antwort

3

Gibt es eine Möglichkeit, die ich kombinieren kann diese als Set mit ihnen zu arbeiten?

Nicht und halten Typ-Sicherheit.

Betrachten Sie zum Beispiel Ihre vorgeschlagenen Code:

var allValidators = new List<IAnswerValidator<QuestionBase, AnswerBase>>(); 
allValidators.AddRange(textAnswers); 
allValidators.AddRange(dateAnswers); 

Angenommen, der Compiler Sie das tun lassen. Dann was sagen Sie sollte passieren, wenn Sie so etwas tun:

QuestionBase question = new TextQuestion(); 
AnswerBase answer = new TextAnswer(); 

foreach (var validator in allValidators) 
{ 
    validator.Validate(question, answer); 
} 

Insbesondere wenn es um das NotChristmasDayValidator Element in der Liste bekommt, was ist das Objekt gehen zu tun, wenn Sie seine Validate() Methode Objekte übergeben, sind nicht DateQuestion bzw. DateAnswer?

Ihr Ziel ist grundlegend gebrochen. Sie sagen, Sie möchten alle Objekte in einer einzigen Liste zusammenfassen, aber Sie haben nicht erklärt, warum das nützlich ist und was Sie mit einer solchen Liste machen könnten. Es gibt natürlich Möglichkeiten, all diese Objekte in die gleiche Liste zu setzen, aber nur durch Verwerfen des Typs Sicherheit. Zum Beispiel, machen Sie einfach Ihr allValidators Objekt ein List<object> stattdessen. Dann können Sie in die Liste setzen, was Sie wollen. Aber wenn Sie die Liste verwenden, müssen Sie später eine zusätzliche Typüberprüfung durchführen.

Bis wann und wenn Sie in der Lage sind, ein Designziel zu erklären, das sicher und sinnvoll ist, können wir vorerst sagen "Nein, das geht nicht, es ist nicht sicher".

+0

Danke Peter. Gut erklärt. –

Verwandte Themen