2010-08-01 18 views
10

Como no sé exactamente qué parte de él solo desencadena el error, no estoy seguro de cómo etiquetarlo mejor.Posible error del compilador C# 4.0, ¿otros pueden verificar?

Esta pregunta es un subproducto de la pregunta SO c# code seems to get optimized in an invalid way such that an object value becomes null, que intenté ayudar Gary con ayer por la noche. Él fue el que descubrió que había un problema, acabo de reducir el problema a un proyecto más simple, y quiero verificación antes de ir más allá con él, de ahí esta pregunta aquí.

Voy a publicar una nota en Microsoft Connect si otras personas pueden verificar que ellos también reciben este problema, y ​​por supuesto espero que sea Jon, Mads o Eric tendrá una mirada en ella, así :)

se trata de:

  • 3 proyectos, 2 de las cuales son las bibliotecas de clases, uno de los cuales es un programa de consola (esto último no es necesario para reproducir el problema, pero sólo muestra la ejecución de este problema, contrario a lo que necesita utilizar el reflector y mirar el código compilado si no lo agrega)
  • Referencias incompletas y tipo inferir rencia
  • Genéricos

El código está disponible aquí: code repository.

Voy a publicar una descripción a continuación de cómo hacer los proyectos si prefieres ensuciarte las manos.

El problema se muestra produciendo un molde no válido en una llamada a método, antes de devolver una lista genérica simple, convirtiéndolo en algo extraño antes de devolverlo. El código original terminó con un lanzamiento a un booleano, sí, un booleano. El compilador agregó un molde de List<SomeEntityObject> a un booleano, antes de devolver el resultado, y la firma del método dijo que devolvería un List<SomeEntityObject>. Esto a su vez genera problemas extraños en el tiempo de ejecución, todo desde el resultado de que la llamada al método se considera "optimizada de distancia" (la pregunta original) o un bloqueo con BadImageFormatException o InvalidProgramException o una de las excepciones similares.

Durante mi trabajo para reproducir esto, he visto un molde a void[], y la versión actual de mi código ahora arroja a TypedReference. En un caso, el Reflector se bloquea, por lo que es muy probable que el código estuviera fuera de toda esperanza en ese caso. Su millaje puede variar.

Esto es lo que debe hacer para reproducirlo:

Nota: No es probable que existan formas más mínimas capaces de reproducir el problema, pero en movimiento todo el código de un solo proyecto hace que desaparezca. Eliminar los genéricos de las clases también hace que el problema desaparezca. El siguiente código reproduce el problema cada vez, así que lo dejo tal como está.

Me disculpo por los caracteres de escape HTML en el código de abajo, esto está de rebajas jugando una mala pasada a mí, si alguien sabe cómo puedo rectificar, por favor hágamelo saber, o simplemente editar la pregunta

  1. Cree una nueva solución de Visual Studio 2010 que contenga una aplicación de consola, para .NET 4.0
  2. Agregue dos proyectos nuevos, ambas bibliotecas de clase, también .NET 4.0 (Me voy a asumir son el nombre y ClassLibrary1 ClassLibrary2)
  3. ajustar todos los proyectos a utilizar todo el tiempo de ejecución de .NET 4.0, no sólo el perfil de cliente
  4. agregar una referencia en el proyecto de consola a ClassLibrary2
  5. Añadir una referencia en ClassLibrary2 a ClassLibrary 1
  6. Retire los dos archivos class1.cs que se agregan de forma predeterminada a las bibliotecas de clases
  7. en ClassLibrary1, agregar una referencia a System.Runtime.Caching
  8. Añadir una nuevo archivo en ClassLibrary1, llámalo DummyCache.cs, y pega i n el siguiente código:

    using System; 
    using System.Collections.Generic; 
    using System.Runtime.Caching; 
    
    namespace ClassLibrary1 
    { 
        public class DummyCache<TModel> where TModel : new() 
        { 
         public void TriggerMethod<T>() 
         { 
         } 
         // Try commenting this out, note that it is never called! 
         public void TriggerMethod<T>(T value, CacheItemPolicy policy) 
         { 
         } 
         public CacheItemPolicy GetDefaultCacheItemPolicy() 
         { 
          return null; 
         } 
         public CacheItemPolicy GetDefaultCacheItemPolicy(IEnumerable<string> dependentKeys, bool createInsertDependency = false) 
         { 
          return null; 
         } 
        } 
    } 
    
  9. añadir un nuevo archivo a ClassLibrary2, lo llaman Dummy.cs y pegar el siguiente código:

    using System; 
    using System.Collections.Generic; 
    using ClassLibrary1; 
    
    namespace ClassLibrary2 
    { 
        public class Dummy 
        { 
         private DummyCache<Dummy> Cache { get; set; } 
         public void TryCommentingMeOut() 
         { 
          Cache.TriggerMethod<Dummy>(); 
         } 
         public List<Dummy> GetDummies() 
         { 
          var policy = Cache.GetDefaultCacheItemPolicy(); 
          return new List<Dummy>(); 
         } 
        } 
    } 
    
  10. Pega el siguiente código en Program.cs en el proyecto de consola:

    using System; 
    using System.Collections.Generic; 
    using ClassLibrary2; 
    
    namespace ConsoleApplication23 
    { 
        class Program 
        { 
         static void Main(string[] args) 
         { 
          Dummy dummy = new Dummy(); 
          // This will crash with InvalidProgramException 
          // or BadImageFormatException, or a similar exception 
          List<Dummy> dummies = dummy.GetDummies(); 
         } 
        } 
    } 
    
  11. Generar, y asegurar que no haya errores de compilación

  12. Ahora intenta ejecutar el programa. Esto debería bloquearse con una de las excepciones más horribles. He visto InvalidProgramException y BadImageFormatException, en función de lo que el elenco terminó como
  13. Mire el código generado de Dummy.GetDummies en Reflector. El código fuente es el siguiente:

    public List<Dummy> GetDummies() 
    { 
        var policy = Cache.GetDefaultCacheItemPolicy(); 
        return new List<Dummy>(); 
    } 
    

    embargo reflector dice (para mí, podría ser diferente en el que echó eligió para usted, y en un caso Reflector incluso estrelló):

    public List<Dummy> GetDummies() 
    { 
        List<Dummy> policy = (List<Dummy>)this.Cache.GetDefaultCacheItemPolicy(); 
        TypedReference CS$1$0000 = (TypedReference) new List<Dummy>(); 
        return (List<Dummy>) CS$1$0000; 
    } 
    

Ahora, aquí hay un par de cosas extrañas, el código de choque anterior/inválido a un lado:

  • Biblioteca2, que tiene Dummy.GetDummies, realiza una llamada para obtener la política de caché predeterminada en la clase desde Library1. Utiliza la inferencia de tipo var policy = ..., y el resultado es un objeto CacheItemPolicy (nulo en el código, pero el tipo es importante).

    Sin embargo, ClassLibrary2 no tiene una referencia a System.Runtime.Caching, por lo que no debe compilarse.

    Y de hecho, si comentar a cabo el método en el muerto que se nombra TryCommentingMeOut, se obtiene:

    El tipo 'System.Runtime.Caching.CacheItemPolicy' se define en una asamblea que no se hace referencia. Debe agregar una referencia al ensamblado 'System.Runtime.Caching, Version = 4.0.0.0, Culture = neutral, PublicKeyToken = b03f5f7f11d50a3a'.

    ¿Por qué tener este método presente hace feliz al compilador? No sé, y ni siquiera sé si esto está relacionado con el problema actual o no. Tal vez es un segundo error.

  • hay un método similar en DummyCache, si restaura el método de Dummy, por lo que el código se compila de nuevo, y luego comentar a cabo el método de DummyCache que tiene el "Intente comentar esto" comentario por encima de ella, se obtener el mismo error de compilación

+0

el tema de reducción del precio es aquí: http://meta.stackexchange.com/questions/19624/markdown-formatting- bug-with-code-blocks-in-lists/19799 # 19799 línea de fondo, realmente evitaría poner código dentro de las listas numeradas a menos que absolutamente * tengas * que. –

+0

Obtengo el mismo problema cuando ejecuto este código (BadImageFormatException). –

+0

Publicado en Microsoft Connect: https://connect.microsoft.com/VisualStudio/feedback/details/585116/possible-compiler-error-in-c-4-0-related-to-generics-missing-project-references- and-type-inference –

Respuesta

2

OK, descargué su código y puedo confirmar el problema como se describe.

No he hecho ningún retoque extenso con esto, pero cuando ejecuto el reflector & una versión de lanzamiento parece todo OK (= excepción de ref nula y desmontaje limpio).
Reflector (6.10.11) se colgó en las compilaciones de Debug.

Un experimento más: me preguntaba sobre el uso de CacheItemPolicies, así que lo reemplacé con mi propio MyCacheItemPolicy (en una 3rd classlib) y aparece la misma excepción BadImageFormat.

La excepción menciona: { "firma binaria Bad (Excepción de HRESULT: 0x80131192)"}

+0

Sí, debería haber mencionado que no creo que haya nada sobre 'CacheItemPolicy' que presente este problema, es cualquier clase que la biblioteca de primera clase sepa que la segunda no. –

+0

Sin embargo, una compilación de versión aún no maneja correctamente la referencia que falta, aún está algo confundida si dejo el método "TryCommentingMeOut" presente. –

+0

¿Puedes definir 'algo confundido'? Continué con MyCacheItemPolicy y si llené la propiedad Caché se ejecuta sin excepción. ¿Dejó la propiedad nula a propósito? Puedo activar/desactivar el problema con la casilla de verificación Optimizar en ClassLib2. –

Cuestiones relacionadas