使用通用接口或类的约束

假设我们写一个测试系统。 测试包含任务列表,每个任务包含问题和答案列表。 我们也假定问题或答案不仅可以是文本,而是可以是例如图像。 所以我们使用泛型:

public interface IQuestion<T> { T Content { get; } } public interface IAnswer<T> { T Content { get; } bool IsCorrect { get; } } 

而当我们创建任务时,就会出现问题:

 interface ITask<TQuestion, TAnswer> { TQuestion Question { get; } List<TAnswer> Answers { get; } } 

如何写TQuestion应该是IQuestionTAnswer子类型 – IAnswer子类型?

我试过了:

 interface ITask<TQuestion, TAnswer> where TQuestion : IQuestion<object> where TAnswer : IAnswer<object> 

但是当我创建:

 class TextQuestion : IQuestion<string> {...} class TextAnswer : IAnswer<string> {...} 

这不起作用:

 class TextTask : ITask<TextQuestion, TextAnswer> 

事实上,事实上, IQuestion<string>不会从IQuestion<object>继承。

Java中 ,我将使用通配符限制ITask泛型类型,在Kotlin中 ,上述方法将起作用。

但如何解决它使用C#?

你需要第三个参数:

 interface ITask<TQuestion, TAnswer, T> where TQuestion : IQuestion<T> where TAnswer : IAnswer<T> 

如您所知, IQuestion<string>不会从IQuestion<object>继承,但这样您可以使用IQuestion<string>作为IQuestion<string>


附录:因为IQuestion没有定义差异 (所以默认情况下是不变的),所以只有IQuestion<object>才是问题。 如果你如下所示定义,你可以使用IQuestion<object>IAnswer )。

 public interface IQuestion<out T> { T Content { get; } } public interface IAnswer<out T> { T Content { get; } bool IsCorrect { get; } } interface ITask<TQuestion, TAnswer> where TQuestion : IQuestion<object> where TAnswer : IAnswer<object> { TQuestion Question { get; } List<TAnswer> Answers { get; } } 

在理解这个问题的方式中,可以通过在ITask引入一个附加的类型参数来形成约束,如下所示,省略之前使用的类型参数TQuestionTAnswer

 interface ITask<T> { IQuestion<T> Question { get; } List<IAnswer<T>> Answers { get; } }