'Delegado 'System.Action' no toma 0 argumentos. Es este un compilador de C # de errores (lambdas + dos proyectos)?

StackOverflow https://stackoverflow.com/questions/4466859

Pregunta

Considere el siguiente código. Se parece perfectamente válido derecha código C #?

//Project B
using System;
public delegate void ActionSurrogate(Action addEvent);
//public delegate void ActionSurrogate2();
// Using ActionSurrogate2 instead of System.Action results in the same error
// Using a dummy parameter (Action<double, int>) results in the same error

// Project A
public static class Class1 {
    public static void ThisWontCompile() {
        ActionSurrogate b = (a) =>
                            {
                                a(); // Error given here
                            };
    }
}

Me sale un error del compilador 'delegado 'Acción' no toma 0 argumentos. en la posición indicada mediante el (Microsoft) C # 4.0 compilador. Tenga en cuenta que usted tiene que declarar ActionSurrogate en un proyecto diferente para este error de manifiesto.

Se pone más interesante:

// Project A, File 1
public static class Class1 {
    public static void ThisWontCompile() {
        ActionSurrogate b = (a) => { a(); /* Error given here */ };
        ActionSurrogate c = (a) => { a(); /* Error given here too */ };
        Action d = () => { };
        ActionSurrogate c = (a) => { a(); /* No error is given here */ };
    }
}

¿He tropiezan con un error compilador de C # aquí?

Tenga en cuenta que este es un error bastante molesto para alguien que le gusta usar lambdas mucho y está tratando de crear una biblioteca de estructuras de datos para su uso futuro ... (Me)

EDIT:. Eliminado caso erronous

copiar y despojado de mi proyecto original al mínimo para que esto suceda. Esto es, literalmente, todo el código en mi nuevo proyecto.

¿Fue útil?

Solución

Esto probablemente es un problema con el tipo inferance, Apperently se infiere del compilador a como un lugar de Action<T> Action (se podría pensar a es ActionSurrogate, que se ajuste a la firma Action<Action>>). Intente especificar el tipo de a explícitamente:

    ActionSurrogate b = (Action a) =>
                        {
                            a();
                        };

Si este no es el caso -. Podría comprobar alrededor de su proyecto para los delegados Action auto definido teniendo un parámetro

Otros consejos

INFORME FINAL DE ACTUALIZACIÓN:

El error se ha corregido en C # 5. Las disculpas de nuevo por las molestias y gracias por el informe.


análisis original:

Me puede reproducir el problema con el compilador de línea de comandos. Ciertamente es un error. Es probablemente mi culpa; Lo siento por eso. (Escribí todo el código de comprobación de conversión de lambda-a delegado.)

Estoy en una tienda de café en este momento y que no tienen acceso a las fuentes del compilador de aquí. Voy a tratar de encontrar algo de tiempo para reproducir esto en la versión de depuración de mañana y ver si puedo averiguar lo que está pasando. Si no encuentro el tiempo, voy a estar fuera de la oficina hasta después de Navidad.

Su observación de que la introducción de una variable del tipo de acción hace que el problema desaparezca es extremadamente interesante. El compilador mantiene muchas memorias caché, tanto por razones de rendimiento y para el análisis requerido por la especificación del lenguaje. Lambdas y variables locales en particular, tienen un montón de almacenamiento en caché de la lógica compleja. Yo estaría dispuesto a apostar tanto como un dólar que algunos caché se está inicializando o se llena en mal aquí, y que el uso de los rellenos de variables locales en el valor justo en el caché.

Gracias por el informe!

ACTUALIZACIÓN: Ahora estoy en el autobús y se me acaba de ocurrir; Creo que sé exactamente lo que está mal. El compilador es perezosa , sobre todo cuando se trata de tipos que vinieron de metadatos. La razón es que podría haber cientos de miles de tipos en los ensamblados de referencia y no hay necesidad de información de carga de todos ellos. Usted va a utilizar mucho menos del 1% de ellos probablemente, por lo que no vamos a perder mucho tiempo y material de carga de memoria que nunca se va a utilizar. De hecho, la pereza es más profundo que eso; un tipo pasa a través de varias "etapas" antes de que pueda ser utilizado. Por primera vez su nombre es conocido, entonces su tipo base, a continuación, si la jerarquía de tipos base está bien fundada (acíclico, etc), entonces sus limitaciones de parámetros tipo, entonces sus miembros, a continuación, si los miembros están bien fundados (que anula anulación algo de la misma firma, y ??así sucesivamente.) Apuesto a que la lógica de conversión está fallando para llamar al método que dice "Asegúrese de que los tipos de todos los parámetros de delegados han sus miembros conocidos", antes se comprueba la firma de la invocación de delegado para la compatibilidad. Sin embargo, el código que hace que una variable local, probablemente hace a hacer eso. Creo que durante la comprobación de la conversión, el tipo de acción podría ni siquiera tener un método de invocación en lo que se refiere al compilador.

Lo sabremos en breve.

ACTUALIZACIÓN: Mis poderes psíquicos son fuertes esta mañana. Cuando los intentos de resolución de sobrecarga para determinar si hay un método "invocación" del tipo de delegado que se lleva a cero argumentos, se encuentra cero métodos de invocación para elegir . Deberíamos asegurar que el tipo delegado metadatos se ha cargado completamente antes de hacer la resolución de sobrecarga. Qué extraño que esto ha pasado desapercibido este largo; Repros que en C # 3.0. Por supuesto que no repro en C # 2.0, simplemente porque no había lambdas; métodos anónimos en C # 2.0 requieren que se indicará el tipo de forma explícita, lo que crea un local, lo que sabemos cargas de los metadatos. Pero me imagino que la causa raíz del error - que la resolución de sobrecarga no obliga a los metadatos de carga para la invocación por -. Remonta a C # 1.0

De todos modos, fascinante de errores, gracias por el informe. Obviamente usted tiene una solución. Voy a tener un seguimiento de control de calidad a partir de aquí y vamos a tratar de lograr que se fija para C # 5. (hemos perdido la ventana de Service Pack 1, que ya se encuentra en fase beta .)

    public static void ThisWontCompile()
        {
            ActionSurrogate b = (Action a) =>
            {
                a();
            };


        }

Esto compilará. Algunos fallo técnico con el compilador su incapaz de encontrar el delegado Acción sin parámetros. Es por eso que está recibiendo el error.

public delegate void Action();
public delegate void Action<T>();
public delegate void Action<T1,T2>();
public delegate void Action<T1,T2,T3>();
public delegate void Action<T1,T2,T3,T4>();
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top