C # возврат к управляемому типу

#c# #dynamic #casting

#c# #динамический #Кастинг

Вопрос:

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

 public partial class Something
{
    List<A> list;
    private void OnLoad(object sender, EventArgs e)
    {
        list = new List<A>();
        list.Add(new B());
        list.Add(new C());
        Debug.WriteLine(list[0].GetType());
        foreach (var item in list)
            DoSomething(item);

    }

    void DoSomething(B b)
    {
        Debug.WriteLine("b");
    }
    void DoSomething(C c)
    {
        Debug.WriteLine("c");
    }

}

interface A
{
}
class B : A
{
}
class C : A
{
}
  

этот код не компилируется, потому что не возникает перегрузки A , но я почти уверен, что делал это раньше. У меня есть рабочее решение. Я могу присвоить элемент списка dynamic переменной, а затем передать его методу. но я видел некоторые тесты, которые показывают, что отражение и динамика очень неэффективны, а производительность для меня очень важна, потому что этот процесс вызывается много раз в секунду.

так что это лучший способ повышения производительности, чем использование dynamic типа для этой цели?

Комментарии:

1. Читайте о шаблоне посетителя

Ответ №1:

Я большой поклонник (неправильного) использования динамических типов для этого, поскольку вы можете восстановить полную информацию о типе, в противном случае потерянную, включая общие параметры. Даже с учетом недавних улучшений языка в сопоставлении с образцом это самый эффективный способ сделать то, что вы хотите сделать.

Компьютеры очень быстры, и использование динамической отправки здесь и там в коде C # вряд ли окажет какое-либо существенное влияние на производительность. Предупреждения о медленности отражения (и есть отражение, участвующее в динамической отправке) несколько устарели, поскольку несколько лет назад были сделаны большие улучшения.

Однако…

Чтобы сделать это правильно, лучшим вариантом в наши дни является использование C # новых операторов переключения, соответствующих типу, например:

 void DoSomething(object obj) {
    switch(obj) {
        case B b:
            Debug.WriteLine("b");
            //here 'b' is available as type 'B'
            break;

        case C c:        
            Debug.WriteLine("c");
            //here 'c' is available as type 'C'
            break;

        default:
            Debug.WriteLine("unsightly default case - necessary for safety");
            throw ...
    }
}