У меня четыре класса:
class BaseA { }
public class DerivedA : BaseA { }
public class BaseB
{
public BaseA SomeProperty { get; set; }
}
public class DerivedB : BaseB
{
public new DerivedA SomeProperty { get; set; }
}
которые используются в программе, например:
static void Main(string[] args)
{
var derivedB = new DerivedB();
derivedB.SomeProperty = new DerivedA();
SomeMethod(derivedB);
}
static void SomeMethod<T>(T param) where T : BaseB
{
var tmp1 = param.SomeProperty; // null
var tmp2 = (param as DerivedB).SomeProperty; // required value
var tmp3 = (param as T).SomeProperty; // null
}
Если я передаю в SomeMethod параметр типа DerivedB, param будет иметь 2 свойства SomeProperty - типов базового и производного классов. Но независимо от типа param, он рассматривается как класс BaseB, и я должен явно привести его к требуемому типу, чтобы получить правильное значение SomeProperty. Приведение к T не помогает.
Должен ли я привести переменную param к ее собственному типу или я могу получить хотя бы свойство с ненулевым значением?
Возможный дубликат ключевое слово "новое" в объявлении свойства в C#





But no matter of what type is param, it is treated as BaseB class and I have to explicitly cast it to required type to get the right SomeProperty value.
Да. Поскольку эта привязка выполняется во время компиляции, в этот момент компилятор знает только о BaseB.SomeProperty. Это свойство, на которое будет ссылаться IL, и свойство, которое будет извлечено во время выполнения.
Я бы сказал, что наличие двух свойств независимый с одинаковым именем действительно сбивает с толку. Если вы В самом деле хотите сделать это, вы можете принудительно выполнить привязку во время выполнения вместо использования динамической типизации:
static void SomeMethod<T>(T param) where T : BaseB
{
dynamic d = param;
// This will use the execution-time type of param
var tmp1 = d.SomeProperty;
}
Но я бы полностью отказался от этого дизайна, если вы можете. Либо имеют отдельно названные свойства, поэтому они явно независимы, либо свойство с частью состояния Один, к которому можно получить доступ по-разному в зависимости от «представления» экземпляра (с риском исключений, если вы установите для свойства значение «неправильное» " тип).
Что вам нужно, так это преобразовать ваш общий к типу class вместо BaseB
а типы параметров - в динамические. Это будет обрабатывать время выполнения ссылок.
static void SomeMethod<T>(T param) where T : class
{
dynamic tmp1 = param;
var myProperty = tmp1.SomeProperty;
}
Кроме того, я не думаю, что здесь действительно нужна слежка.
Кроме того, вы можете удалить тип для общего. Он по-прежнему будет работать в вашем случае
Просто
static void SomeMethod<T>(T param)
Затенение базового свойства, вероятно, не лучший способ.
В вашем крошечном образце базовый и производный классы пусты, поэтому немного сложно определить, что именно вам нужно.
На ум приходят два более простых и понятных способа:
подумайте о создании интерфейса, который будет реализовывать базовый класс, производный класс и общий тип (используемый в SomeMethod) ... и тогда это довольно просто
если общий интерфейс не подходит для ваших нужд, рассмотрите возможность создания базового класса как универсального класса.
Надеюсь это поможет
Все эти проблемы возникают из-за того, что вы скрываете свойство baseB в производномB. Почему бы также не сделать свойство baseB универсальным?