2010-07-12 11 views
27

Soy interesante en algunas elecciones de diseño de lenguaje C#. Hay una regla en la especificación C# que permite utilizar grupos de métodos como las expresiones de is operador:C# Language Design: grupo de métodos dentro del operador `is`

class Foo { 
    static void Main() { if (Main is Foo) Main(); } 
} 

condición anterior siempre es falsa, ya que la especificación dice:

7.10.10 El es el operador

Si e es un grupo método o la nula literal, de si el tipo de e es un tipo de referencia o un tipo anulable y el valor de e es nulo, el resultado es falso.

Mis preguntas: cuál es el propósito/punto/razón de que permite utilizar el elemento de lenguaje C# con ninguna representación en tiempo de ejecución CLR como grupos de métodos tales dentro del operador de "tiempo de ejecución" como is?

+2

+1 _no pista _... – SLaks

+0

Eso es ... deslumbrante. La sección en el operador 'as' no menciona los grupos de métodos. –

+0

@Tim: Pero el operador "como" se define como un azúcar sintáctico para una combinación de moldes, el operador condicional y el operador "es", por lo que el operador "como" no necesita mencionar grupos de métodos. –

Respuesta

21

cuál es el propósito/punto/razón de que permite utilizar el elemento de lenguaje C# con ninguna representación en tiempo de ejecución CLR como grupos de métodos tales dentro del operador de "tiempo de ejecución" como es?

El archivo de notas de diseño de idiomas no hace mención de por qué se tomó esta decisión, por lo que cualquier conjetura sobre una respuesta será una conjetura. Mencionan que si el resultado del "es" puede determinarse estáticamente para que siempre sea verdadero o falso, que así se determine y genere una advertencia. Parece plausible que esto podría ser simplemente un error.

La razón más común para convertir lo que podría ser un error en una advertencia (o simplemente permitirlo) es que eso disminuye la carga sobre los productores de programas que generan código automáticamente. Sin embargo, no veo un escenario realmente convincente aquí.

UPDATE:

I acaba de comprobar la especificación C# 1.0. No tiene este lenguaje en eso. No dice nada sobre los nulos o los argumentos del grupo de métodos. Y, por supuesto, no dice nada sobre las conversiones de grupos de métodos porque en C# 1.0 no hubo conversiones de grupos de métodos implícitos; tenía que llamar explícitamente "nuevo D (M)" si quería convertir el método M para delegar el tipo D.

Este último punto es la justificación para que "M sea D" devuelva falso en lugar de verdadero; No se puede decir legalmente "D d = M"; Entonces, ¿por qué "M is D" es verdad?

Por supuesto, en C# 2.0 esto tiene menos sentido, ya que puede decir "D d = M"; en C# 2.0.

También le pregunté a una de las personas presentes cuando se diseñó el operador "es" y él no tenía ningún recuerdo de haber decidido alguna vez esta pregunta de una forma u otra. Sospechaba que el diseño original del operador "es" era no dar ningún error, solo advertencias, y que todo el texto en la especificación sobre qué hacer con los grupos de métodos y nulos y lo que fuera, se agregaba post hoc, para el Versión de C# 2.0 de la especificación, y basada en lo que realmente hizo el compilador.

En resumen, parece que este fue un agujero de diseño en C# 1.0 que se empaquetó cuando la especificación se actualizó para C# 2.0. No parece que este comportamiento específico sea deseado e implementado deliberadamente.

Esta teoría se ve reforzada por el hecho de que los métodos anónimos do producen un error cuando se usan como argumento para "es" en C# 2.0. No sería un cambio rotundo hacerlo, pero sería ser un cambio de última hora para que "M is D" repentinamente comience a ser verdadero o sea un error.

ADEMÁS DE ACTUALIZACIÓN:

Si bien la investigación de este he aprendido algo interesante. (Para mí.) Cuando la función se diseñó originalmente, el diseño debía permitir el nombre de un tipo, o un objeto Tipo como el argumento de la derecha para "es". Esa idea fue abandonada mucho antes de que se enviara C# 1.0.

3

primer lugar un método no es un tipo, de MSDN indica claramente lo siguiente:

el operador is is utilizado para comprobar si el tipo de tiempo de ejecución de un objeto es compatible con un tipo dado

Ejemplo

public static void Test (object o) 
{ 
    Class1 a; 

    if (o is Class1) {} 
} 

From MSDN:

An es expresión se evalúa a verdadero si se cumplen ambos de los siguientes condiciones:

  • expresión no es nulo.
  • expresión se puede convertir a tipo. Es decir, una expresión moldeada de la forma (tipo) (expresión) se completará sin lanzar una excepción. Para obtener más información, consulte 7.6.6 Expresiones de molde.

Así que la razón de su ejemplo siendo tierras falsas en el segundo punto, tiene que ser moldeable a un tipo específico.

Espero no haber perdido la comprensión de la pregunta.

+1

La pregunta es, ¿por qué 'Main is Class1' no es un error del compilador? – SLaks

+0

@SLacks: Tal vez deberíamos usar Reflector para investigar más a fondo esto. – Andreas

+0

@SLaks, usando ReShaper recibo una advertencia con este mensaje: "La expresión dada nunca proporciona un tipo". Comprobando con Reflector ahora ... –