2017-01-03 3 views
17

Я обновил свой проект до целевого C# 7 и использовал Visual Studio 2017 RC для реализации соответствия шаблону в моем решении. После этого были введены некоторые ошибки, связанные с сопоставлением шаблонов с общими параметрами.Выражение типа T не может обрабатываться шаблоном типа X

Рассмотрим следующий код:

public class Packet 
{ 
} 

public class KeepalivePacket : Packet 
{ 
} 

public void Send<T>(T packet) 
    where T : Packet 
{ 
    if (packet is KeepalivePacket keepalive) 
    { 
     // Do stuff with keepalive 
    } 

    switch (packet) 
    { 
     case KeepalivePacket keepalivePacket: 
      // Do stuff with keepalivePacket 
      break; 
    } 
} 

Оба if заявление и case заявление к ошибке компиляции.

Выражение типа Т не может быть обработан с помощью шаблона типа KeepalivePacket

Если я сначала привести параметр к типу object шаблон согласования работы, как и ожидалось. Затем Рослин отличает бросок до object как избыточный.

if ((object)packet is KeepalivePacket keepalive) 
{ 
    // This works 
} 

Эта ошибка применяется только к общим параметрам и переменным. Roslyn, похоже, не знает об этой проблеме, так как рекомендует изменить код для использования сопоставления шаблонов с помощью анализатора и позволяет применить «исправление кода», приводящее к повреждению кода.

+0

Похоже, что * плохой дизайн * если вам нужно включить тип объекта. На самом деле оператор 'is' является тем, кто уже считается« плохим запахом »... –

+3

@WillemVanOnsem должно быть достаточно вариантов использования для сопоставления шаблонов для команды C#, чтобы добавить его в спецификацию, нет? –

+0

Действительно, просто потому, что в большинстве промышленных приложений невозможно сначала спроектировать всю вещь: она слишком сложна. Но фактически каждый оператор 'is' и т. Д. Лучше заменяется динамическими привязками, так как они более типичны. –

ответ

12

Как explained by Neal Gafter от Microsoft:

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

Мы не собираемся ничего с этим делать в C# 7. Вам нужно будет добавить бросок к вашему коду, чтобы обойти его. Как только у нас будут рекурсивные шаблоны, это может быть труднее обойти. Более того, неудобное языковое правило, лежащее в основе этой проблемы (т. Е. Отсутствие преобразования из T в KeepalivePacket), не имеет большого смысла.

Смежные вопросы