Передача сущности производного класса в универсальные методы - PullRequest
0 голосов
/ 06 июня 2018

У меня есть четыре класса, например:

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.Приведение к Т не помогает.Должен ли я приводить переменную param к ее собственному типу или я могу получить хотя бы свойство с ненулевым значением?

Ответы [ 3 ]

0 голосов
/ 06 июня 2018

Вам нужно преобразовать ваш универсальный тип class вместо BaseB и типы параметров в динамический.Это будет обрабатывать ссылки во время выполнения.

static void SomeMethod<T>(T param) where T : class
        {
            dynamic tmp1 = param; 
            var myProperty = tmp1.SomeProperty;
        }

Кроме того, я не думаю, что затенение здесь действительно необходимо.

Кроме того, вы можете удалить тип для универсального.Это все еще будет работать в вашем случае

Просто

static void SomeMethod<T>(T param)
0 голосов
/ 06 июня 2018

Слежение за базовым свойством, вероятно, не лучший способ.

С вашим крошечным образцом базовые и производные классы пусты, поэтому немного сложно определить, что именно вам нужно.

Имеются в виду два более понятных и простых способа:

  • рассмотреть возможность создания интерфейса, который будут реализовывать базовый класс, производный класс и универсальный тип (используемый в SomeMethod).... и тогда довольно просто

  • , если общий интерфейс невозможен для ваших нужд, рассмотрите возможность создания базового класса как универсального класса

Надеюсь, это поможет

0 голосов
/ 06 июня 2018

Но независимо от того, какой тип является param, он обрабатывается как класс BaseB, и я должен явно привести его к требуемому типу, чтобы получить правильное значение SomeProperty.

Да.Поскольку это связывание выполняется во время компиляции, в этот момент компилятор знает только о 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;
}

Но я бы полностью избежал этой схемы, если бы вы могли,Либо имеют отдельно названные свойства, поэтому они, очевидно, независимы, либо свойство с единичным элементом состояния, к которому можно получить доступ по-разному в зависимости от «представления» экземпляра (с риском исключений, если вы установитесвойство «неправильного» типа).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...