Poniżej może być ogólna wiedza, której po prostu mi brakowało, ale eh. Jakiś czas temu mieliśmy przypadek błędu, który zawierał właściwości wirtualne. Trochę abstrakcji kontekstu, rozważ następujący kod i zastosuj punkt przerwania do określonego obszaru:
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 { } }
}
W Derived
kontekście obiektowym takie samo zachowanie można uzyskać podczas dodawania base.Property
jako zegarka lub pisania base.Property
w szybkim zegarku .
Zajęło mi trochę czasu, aby zrozumieć, co się dzieje. W końcu oświecił mnie Quickwatch. Gdy wchodzisz do Quickwatch i eksplorujesz Derived
obiekt d (lub z kontekstu obiektu this
) i base
wybierasz pole , pole edycyjne na górze Quickwatch wyświetla następującą obsadę:
((TestProject1.Base)(d))
Co oznacza, że jeśli podstawa zostanie zastąpiona jako taka, połączenie będzie
public string BaseProperty { get { return ((TestProject1.Base)(d)).Property; } private set { } }
dla Zegarków, Quickwatcha i etykiet debugowania kursora myszy, a wtedy byłoby sensowne, aby wyświetlał się "AWESOME"
zamiast "BASE_AWESOME"
rozważać polimorfizm. Nadal nie jestem pewien, dlaczego przekształciłby go w obsadę. Jedna hipoteza jest taka, że call
może nie być dostępna z kontekstu tych modułów i tylko callvirt
.
W każdym razie, to oczywiście niczego nie zmienia pod względem funkcjonalności, Derived.BaseProperty
nadal naprawdę powróci "BASE_AWESOME"
, a zatem nie było to przyczyną naszego błędu w pracy, a jedynie mylący element. Uważam jednak za interesujące, w jaki sposób może wprowadzić w błąd programistów, którzy nie byliby tego świadomi podczas sesji debugowania, szczególnie jeśli Base
nie jest ujawniony w projekcie, ale jest nazywany zewnętrzną biblioteką DLL, co powoduje, że deweloperzy mówią:
„Oi, czekaj… jak to jest, że DLL jest,. Robić coś śmiesznego”