method - how to use func c#
¿Apoya C#la covarianza de tipo de retorno? (9)
Colocar esto en el objeto MyControl funcionaría:
public new MyPage Page {get return (MyPage)Page; set;}''
No puede anular la propiedad porque devuelve un tipo diferente ... pero puede redefinirla.
No necesita covarianza en este ejemplo, ya que es relativamente simple. Todo lo que está haciendo es heredar la Page
del objeto base desde MyPage
. Cualquier Control
que desee devolver MyPage
lugar de Page
necesita redefinir la propiedad de página del Control
Estoy trabajando con .NET Framework y realmente quiero poder crear un tipo de página personalizado que use todo mi sitio web. El problema surge cuando intento acceder a la página desde un control. Deseo 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; }
}
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;
}
Esta serie de publicaciones de blog analiza en detalle el problema de la covarianza del tipo de devolución, e incluso habla sobre cómo hacerlo con IL.
http://www.simple-talk.com/community/blogs/simonc/archive/2010/07/14/93495.aspx
http://www.simple-talk.com/community/blogs/simonc/archive/2010/07/16/93516.aspx
http://www.simple-talk.com/community/blogs/simonc/archive/2010/07/19/93562.aspx
Perdón por solo publicar enlaces, pero es bastante detallado y citar fragmentos aquí no sería tan útil. Muestra cómo se puede lograr usando el código IL.
Lo haré de esta manera:
class R {
public int A { get; set; }
}
class R1: R {
public int B { get; set; }
}
class A
{
public R X { get; set; }
}
class B : A
{
private R1 _x;
public new R1 X { get => _x; set { ((A)this).X = value; _x = value; } }
}
No lo he probado, pero ¿no funciona?
YourPageType myPage = (YourPageType)yourControl.Page;
Parece que lo que quieres es devolver la covarianza tipo. C # no es compatible con la covarianza de tipo de retorno.
La covarianza del tipo de devolución es donde anula un método de clase base que devuelve un tipo menos específico con 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 Contents via Enclosure esperan que Animal, y Aquarium prometan no solo cumplir ese requisito, sino también hacer una promesa más estricta: que el animal siempre es un pez.
Este tipo de covarianza no es compatible con C # y es poco probable que alguna vez sea compatible. No es compatible con CLR. (Es compatible con C ++ y con la implementación de C ++ / CLI en el CLR; lo hace generando métodos de ayuda mágica del tipo que sugiero a continuación).
(Algunos lenguajes también admiten la contravariancia del tipo de parámetro formal, que puede anular un método que toma un pez con un método que toma un animal. De nuevo, se cumple el contrato; la clase base requiere que se maneje cualquier pez, y el derivado la clase promete no solo manipular peces, sino cualquier animal. Del mismo modo, C # y CLR no son compatibles con la contravariancia del tipo de parámetro formal).
La forma en que puede evitar 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 obtener una escritura más fuerte cuando utilizas algo del tipo Acuario en tiempo de compilación.
Puede acceder a su página desde cualquier control caminando por el árbol padre. Es decir
myParent = this;
while(myParent.parent != null)
myParent = myParent.parent;
* No compila ni prueba.
O bien, obtenga la página principal en el contexto actual (depende de su versión).
Entonces, lo que me gusta hacer es esto: creo una interfaz con las funciones que quiero usar en el control (por ejemplo, IHostingPage)
Luego lanzo la página principal ''IHostingPage host = (IHostingPage) Parent;'' y estoy todo listo para llamar a la función en la página que necesito de mi control.
Sí, admite la covarianza, pero depende de lo exacto que intenta lograr.
También tiendo a usar genéricos mucho para las cosas, lo que significa que cuando haces algo como:
class X<T> {
T doSomething() {
}
}
class Y : X<Y> {
Y doSomethingElse() {
}
}
var Y y = new Y();
y = y.doSomething().doSomethingElse();
Y no "pierdas" tus tipos.
Sí. Hay varias formas de hacerlo, y esta es solo una opción:
Puede hacer que su página implemente alguna interfaz personalizada que expone un método llamado "GetContext" o algo así, y devuelve su información específica. Entonces su control puede simplemente solicitar la página y el elenco:
var myContextPage = this.Page as IMyContextGetter;
if(myContextPage != null)
var myContext = myContextPage.GetContext();
Entonces puedes usar ese contexto como quieras.