¿Por qué una implementación de interfaz no puede devolver un tipo más específico?

Si una interfaz especifica una propiedad o método para devolver otra interfaz, ¿por qué no se permite que las implementaciones de la primera interfaz “cambien” el tipo de retorno a un tipo más específico?

Tomemos un ejemplo para ilustrar:

interface IFoo { IBar GetBar(); } interface IBar { } class Foo : IFoo { // This is illegal, we are not implementing IFoo properly public Bar GetBar() { return new Bar(); } } class Bar : IBar { } 

cómo hacerlo funcionar, esa no es mi preocupación.

Yo solo puedo:

  • Cambie el tipo de GetFoo() de GetFoo() a IBar , o
  • Implementar explícitamente la interfaz y simplemente llamar a GetBar desde el método IFoo.GetBar()

Lo que realmente estoy preguntando es el razonamiento para no solo permitir que se compile el código anterior. ¿Hay algún caso en el que lo anterior no cumpla con el contrato especificado por IFoo ?

Por lo general, diría que sería un caso de equilibrio entre el beneficio y la complejidad adicional de respaldar tal característica. (Todas las funciones requieren esfuerzo para diseñar, documentar, implementar, probar y, luego, los desarrolladores también deben conocerlos). Tenga en cuenta que podría haber algunas complejidades significativas si quisiera admitir la devolución de un tipo de valor que implementa una interfaz, por ejemplo. (ya que eso termina en una representación diferente, en lugar de solo una referencia).

En este caso, no creo que el CLR sea compatible con esta característica, lo que haría muy difícil que C # lo haga de manera limpia.

Estoy de acuerdo en que sería una característica útil, pero sospecho que no se ha considerado lo suficientemente útil como para justificar el trabajo adicional requerido.

La función que está preguntando se llama “covarianza de tipo de retorno” . Como se señala en Wikipedia , Java y C ++ lo tienen, lo que quizás sorprenda que C # no lo tenga.

Eric Lippert confirma en los comentarios de esta respuesta que esta característica no se implementó porque no valió la pena el esfuerzo de implementación. (Una revisión previa de esta respuesta asignó la responsabilidad de esa decisión a Eric personalmente; dice que esto es incorrecto, y que si una persona es responsable, era Anders Hejlsberg).

Independientemente, ahora hay varias propuestas para agregarlo al lenguaje (consulte https://github.com/dotnet/roslyn/issues/357 , https://github.com/dotnet/csharplang/blob/master/proposals/covariant -returns.md , https://github.com/kingces95/coreclr/issues/2 ), por lo que quizás se implemente en los próximos años. Según esas discusiones, no parece que existan razones profundas por las cuales la característica no debería existir en C # en principio , sino que, hasta el momento, nunca se ha considerado que valga la pena el esfuerzo de nadie.