c# pattern-matching visual-studio-2017 c#-7.0

c# - La expresión del tipo T no puede ser manejada por un patrón del tipo X



pattern-matching visual-studio-2017 (2)

He actualizado mi proyecto para apuntar a C # 7 y usé Visual Studio 2017 RC para implementar la coincidencia de patrones en mi solución. Después de hacer esto, se introdujeron algunos errores relacionados con la coincidencia de patrones con parámetros genéricos.

Considere el siguiente código:

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; } }

Tanto la sentencia if como la sentencia case producen un error de compilación.

Una expresión de tipo T no puede ser manejada por un patrón de tipo KeepalivePacket

Si primero convierto el parámetro para escribir el object la coincidencia de patrón funciona como se esperaba. Roslyn luego marca el elenco para object como redundante.

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

Este error solo parece aplicarse a parámetros y variables genéricos. Parece que Roslyn no está al tanto de este problema ya que recomienda cambiar el código para usar la coincidencia de patrones a través de un analizador y me permite aplicar la "corrección de código" que resulta en el código roto.


C # 7.1 apoya esto ahora. Por ejemplo, consulte "Coincidencia de patrones con genéricos" en este artículo . Es posible que deba agregar <LangVersion>7.1</LangVersion> o <LangVersion>latest</LangVersion> a su archivo de proyecto. Consulte here para obtener detalles sobre la configuración de LangVersion .


Como explicó Neal Gafter de Microsoft:

La razón por la que no funciona es que no hay una conversión (explícita o implícita) definida de T a KeepalivePacket. La coincidencia de patrones requiere que exista tal conversión, tal como se define en términos del operador de conversión, que requiere que exista una conversión. La especificación de lenguaje y el compilador aceptan que no existe conversión. Me parece extraño que la especificación del lenguaje se defina de tal manera que no exista una conversión (explícita) aquí. Vamos a ver qué podemos hacer al respecto.

No vamos a hacer nada al respecto en C # 7. Tendrá que agregar una conversión a su código para solucionarlo. Una vez que tenemos patrones recursivos, esto puede ser más difícil de solucionar. Además, la regla de lenguaje torpe que subyace a este problema (es decir, que no hay conversión de T a KeepalivePacket) no tiene mucho sentido.

Actualizar

Esto ahora está trabajando en C # 7.1