2012-08-13 13 views
10

Si tengo una lambda como () => { throw new Exception(); }, no está claro si tiene un tipo de devolución o no. Debido a esto, puede convertirse (implícitamente) en Action y Func<object> (o en cualquier otro Func<T>). Esto se debe a que, de acuerdo con el apartado 6.5 conversiones función anónima de la especificación C# 4:Conversiones de Lambda con un tipo de retorno no claro y resolución de sobrecarga

[A] delegado tipo D es compatible con una función anónima F proporcionado:

  • ...

  • Si D tiene un tipo de devolución void y el cuerpo de F es un bloque de instrucciones, cuando [...] el cuerpo de F es un bloque de instrucción válido en el que ninguna instrucción de retorno especifica una expresión.

  • Si D tiene un tipo de retorno no nulo y el cuerpo de F es un bloque de instrucciones, cuando [...] el cuerpo de F es un bloque de instrucciones es válido con un punto extremo no alcanzable en el que cada uno return especifica los estados una expresión que es implícitamente convertible al tipo de devolución de D.

Pero si tengo dos sobrecargas de un método, donde uno tiene un parámetro de tipo Action y el otro Func<object>, y lo paso la lambda desde arriba, se utiliza la sobrecarga Func<object>. ¿Por qué? ¿Qué parte de la especificación dice que Func<object> es mejor que Action en este caso?

He examinado §7.5.3.2 Mejor miembro de función, pero eso no lo explica.

+0

Y si, en lugar de la sintaxis lambda, se utiliza la notación 'delegate {throw new Exception(); } 'donde dejas fuera la lista de parámetros en'() 'paréntesis, esa función anónima podría coincidir con ** cualquier ** firma delegada, supongo, incluyendo también p. ej. 'EventHandler' y' Action '. –

+0

@JeppeStigNielsen Sí. En ese caso, no existe una regla para eliminar la ambigüedad como parámetros del método, por lo que obtendría un error de compilación. – svick

Respuesta

11

Debería haber buscado una sección inferior: §7.5.3.3 mejor conversión de la expresión explica que:

Dada una conversión implícita C1 que convierte de una expresión E a un tipo T1, y una conversión implícita C2 que convierte de una expresión E a un tipo T2, C1 es una conversión mejor que C2 si al menos uno de los siguientes sostiene:

  • ...

  • E es una función anónima, T1 es o bien un tipo de delegado D1 o un tipo de árbol de expresión Expression<D1>, T2 es o bien un tipo de delegado D2 o un árbol de expresión de tipo Expression<D2> y uno de cumple lo siguiente:

    • ...

    • D1 y D2 tienen listas de parámetros idénticos, y una de las siguientes bodegas:

      • ...

      • D1 tiene un tipo de retorno Y y D2 falto de regresar

+1

¿Ha publicado esta respuesta en el mismo segundo en que hizo la pregunta? –

+6

Sí, mientras escribía la pregunta, noté la respuesta en la especificación. Así que no quería perder el tiempo de nadie investigando esto. Pero al mismo tiempo, pensé que podría ser útil para otra persona. – svick

+1

Esta respuesta explica cómo el comportamiento observado se ajusta a la especificación, pero no explica (y no puede) por qué la especificación se escribió de esa manera en primer lugar. Afortunadamente, [ahora tenemos la palabra] (http://stackoverflow.com/questions/24316189/peculiar-overload-resolution-with-while-true/24316474?noredirect=1#comment37681268_24316474) de la persona que implementó la función en el compilador explicando eso también! – Jon

Cuestiones relacionadas