Lo siguiente podría ser conocimiento general que simplemente me faltaba, pero eh. Hace algún tiempo, tuvimos un caso de error que incluía propiedades virtuales. Resumiendo un poco el contexto, considere el siguiente código y aplique el punto de interrupción al área especificada:
class Program
{
static void Main(string[] args)
{
Derived d = new Derived();
d.Property = "AWESOME";
}
}
class Base
{
string _baseProp;
public virtual string Property
{
get
{
return "BASE_" + _baseProp;
}
set
{
_baseProp = value;
//do work with the base property which might
//not be exposed to derived types
//here
Console.Out.WriteLine("_baseProp is BASE_" + value.ToString());
}
}
}
class Derived : Base
{
string _prop;
public override string Property
{
get { return _prop; }
set
{
_prop = value;
base.Property = value;
} //<- put a breakpoint here then mouse over BaseProperty,
// and then mouse over the base.Property call inside it.
}
public string BaseProperty { get { return base.Property; } private set { } }
}
Mientras está en el Derived
contexto del objeto, puede obtener el mismo comportamiento al agregar base.Property
como reloj o al escribir base.Property
en el reloj rápido.
Me tomó un tiempo darme cuenta de lo que estaba pasando. Al final fui iluminado por el Quickwatch. Al ingresar al Quickwatch y explorar el Derived
objeto d (o desde el contexto del objeto this
) y seleccionar el campo base
, el campo de edición en la parte superior del Quickwatch muestra el siguiente reparto:
((TestProject1.Base)(d))
Lo que significa que si la base se reemplaza como tal, la llamada sería
public string BaseProperty { get { return ((TestProject1.Base)(d)).Property; } private set { } }
para los Watches, Quickwatch y la información sobre herramientas de depuración del mouse, y entonces tendría sentido que se muestre en "AWESOME"
lugar de "BASE_AWESOME"
cuando se considera el polimorfismo. Todavía no estoy seguro de por qué lo transformaría en un elenco, una hipótesis es que call
podría no estar disponible desde el contexto de esos módulos, y solo callvirt
.
De todos modos, eso obviamente no altera nada en términos de funcionalidad, Derived.BaseProperty
todavía volverá realmente "BASE_AWESOME"
, y por lo tanto, esta no fue la raíz de nuestro error en el trabajo, simplemente un componente confuso. Sin embargo, me pareció interesante cómo podría engañar a los desarrolladores que desconocen ese hecho durante sus sesiones de depuración, especialmente si Base
no se expone en su proyecto, sino que se hace referencia a él como un archivo DLL de terceros, lo que hace que los desarrolladores simplemente digan:
"Oi, espera ... ¿qué? Dios mío es como DLL, haciendo algo gracioso"