¿C# admite la covarianza del tipo de retorno?

Resuelto Kyle Sletten asked hace 13 años • 9 respuestas

Estoy trabajando con .NET Framework y realmente quiero poder crear un tipo de página personalizada que utilice todo mi sitio web. El problema surge cuando intento acceder a la página desde un control. Quiero poder devolver mi tipo específico de página en lugar de la página predeterminada. ¿Hay alguna manera de hacer esto?

public class MyPage : Page
{
    // My own logic
}

public class MyControl : Control
{
    public MyPage Page { get; set; }
}
Kyle Sletten avatar Apr 19 '11 04:04 Kyle Sletten
Aceptado

ACTUALIZACIÓN: Esta respuesta se escribió en 2011. Después de dos décadas de personas que propusieron covarianza de tipo de retorno para C#, se implementaron. Consulte Rendimientos covariantes en https://devblogs.microsoft.com/dotnet/c-9-0-on-the-record/ .


Parece que lo que quieres es la covarianza del tipo de retorno. C# no admite la covarianza del tipo de retorno.

La covarianza del tipo de retorno es donde se anula un método de clase base que devuelve un tipo menos específico por uno que devuelve un tipo más específico:

abstract class Enclosure
{
    public abstract Animal Contents();
}
class Aquarium : Enclosure
{
    public override Fish Contents() { ... }
}

Esto es seguro porque los consumidores de Contenidos a través de Enclosure esperan un animal, y Aquarium promete no sólo cumplir ese requisito, sino además, hacer una promesa más estricta: que el animal siempre será un pez.

Este tipo de covarianza no se admite en C# y es poco probable que alguna vez se admita. No es compatible con el CLR. (Es compatible con C++ y con la implementación de C++/CLI en CLR; lo hace generando métodos auxiliares mágicos del tipo que sugiero a continuación).

(Algunos lenguajes también admiten la contravarianza del tipo de parámetro formal: se puede anular un método que toma un Pez con un método que toma un Animal. Nuevamente, el contrato se cumple; la clase base requiere que se maneje cualquier Pez, y el derivado (La clase promete no solo manejar peces, sino también cualquier animal. De manera similar, C# y CLR no admiten la contravarianza de tipos de parámetros formales).

La forma de solucionar esta limitación es hacer algo como:

abstract class Enclosure
{
    protected abstract Animal GetContents();
    public Animal Contents() { return this.GetContents(); }
}
class Aquarium : Enclosure
{
    protected override Animal GetContents() { return this.Contents(); }
    public new Fish Contents() { ... }
}

Ahora obtienes los beneficios de anular un método virtual y una escritura más fuerte cuando usas algo del tipo Aquarium en tiempo de compilación.

Eric Lippert avatar Apr 18 '2011 21:04 Eric Lippert

Con las interfaces lo solucioné implementando explícitamente la interfaz:

public interface IFoo {
  IBar Bar { get; }
}
public class Foo : IFoo {
  Bar Bar { get; set; }
  IBar IFoo.Bar => Bar;
}
ChetPrickles avatar Sep 29 '2017 13:09 ChetPrickles