Подтвердить что ты не робот

Выражение типа T не может обрабатываться шаблоном типа X

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

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

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 создают ошибку компиляции.

Выражение типа T не может обрабатываться шаблоном типа KeepalivePacket

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

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

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

4b9b3361

Ответ 1

Как объясняется Нилом Гафтером от Microsoft:

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

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