Наступне може бути загальним знанням, якого мені просто бракувало, але так. Деякий час тому у нас був випадок помилки, який включав віртуальні властивості. Трохи абстрагуючи контекст, врахуйте наступний код і застосуйте точку розриву до вказаної області:
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 { } }
}
Перебуваючи в Derived
контексті об'єкта, ви можете отримувати таку саму поведінку під час додавання base.Property
годинника або введення base.Property
в швидкий годинник.
Знадобилося трохи часу, щоб зрозуміти, що відбувається. Врешті-решт мене просвітив Швидкий годинник. Під час заходу в Quickwatch та вивчення Derived
об'єкта d (або з контексту об'єкта this
) та вибору поля base
, поле редагування у верхній частині Quickwatch відображає такий склад:
((TestProject1.Base)(d))
Що означає, що якщо база буде замінена як така, то дзвінок був би
public string BaseProperty { get { return ((TestProject1.Base)(d)).Property; } private set { } }
для інструментів "Годинники", "Швидкий годинник" та налагодження миші за налагодженням, і тоді це має сенс відображати "AWESOME"
замість того, "BASE_AWESOME"
щоб розглянути питання про поліморфізм. Я все ще не впевнений, чому це перетворило б його в склад, одна з гіпотез - це call
може бути недоступно лише з контексту цих модулів callvirt
.
Так чи інакше, це, очевидно, нічого не змінює з точки зору функціональності, Derived.BaseProperty
все одно дійсно повернеться "BASE_AWESOME"
, і, таким чином, це не було коренем нашої помилки на роботі, просто заплутаною складовою. Однак мені було цікаво, як це може ввести в оману розробників, які не знають про цей факт під час сеансів налагодження, особливо якщо Base
це не викрито у вашому проекті, а посилається на сторонні DLL, в результаті чого Devs просто сказав:
"Ой, зачекайте. Що? Омг, схожий на DLL, .. роблячи щось смішне"