#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 ...
}
}