.net - studio - microsoft office interop excel visual basic
¿Por qué hay una diferencia en el comportamiento de una aplicación construida en VS 2010 vs VS 2012? (2)
Estaba comprobando si la instalación de .NET 4.5 en nuestras máquinas de compilación cambia la imagen IL de salida generada por VS 2010.
Como sé que el comportamiento de foreach ha cambiado en .NET 4.5 para evitar problemas debido al cierre de Access to Modified , elegí una aplicación simple que mostraba el comportamiento.
class Program
{
private static void Main(string[] args)
{
var contents = new List<Func<int>>();
var s = new StringBuilder();
int[] values = new int[] { 4, 5, 6 };
foreach (int value in values)
{
contents.Add(() => value);
}
for (var k = 0; k < contents.Count; k++)
s.Append(contents[k]());
Console.WriteLine(s);
}
Salida VS 2010 : 666
Salida VS 2012 : 456
Creé una aplicación de consola en VS 2010 y una aplicación de consola con el mismo código en VS 2012 (ambos .NET 4 orientados).
Sin embargo, ambas aplicaciones de la consola mostraron comportamientos diferentes según el IDE con el que se crearon. En la salida de compilación, verifiqué que ambos tenían argumentos de compilación casi similares. ¿Entonces me preguntaba cómo el ejecutable final exhibió un comportamiento diferente? .NET 4.5 es una actualización in situ, por lo que el compilador para ambos IDEs debe ser el mismo.
NOTA: Sí eché un vistazo a una pregunta relacionada: Respuesta LINQ diferente en VS 2010 y VS 2012, pero no contesté mi pregunta sobre por qué el comportamiento del ejecutable era diferente.
EDIT 1: Como mencionó mletterle , mletterle el código utilizando la línea de comandos en la ventana de resultados de VS 2010 en un indicador de comandos de VS 2010. La salida resultante se comportó como si se hubiera construido con VS 2012.
EDIT 2:
Estoy publicando la salida presente en la ventana de salida:
VS 2010: La construcción comenzó el 20/12/2012 11:04:56 PM.
CoreClean: Creando el directorio "obj / x86 / Debug /". GenerateTargetFrameworkMonikerAttribute: Se omite el destino "GenerateTargetFrameworkMonikerAttribute" porque todos los archivos de salida están actualizados con respecto a los archivos de entrada. CoreCompile:
C: / Windows / Microsoft.NET / Framework / v4.0.30319 / Csc.exe / noconfig / nowarn: 1701,1702 / nostdlib + / platform: x86 / errorreport: prompt / warn: 4 / define: DEBUG; TRACE / errorendlocation / preferreduilang : en-US / highentropyva- / reference: "C: / Archivos de programa (x86) / Reference Assemblies / Microsoft / Framework.NETFramework / v4.0 / Microsoft.CSharp.dll" / reference: "C: / Archivos de programa (x86 ) / Reference Assemblies / Microsoft / Framework.NETFramework / v4.0 / mscorlib.dll "/ reference:" C: / Archivos de programa (x86) / Reference Assemblies / Microsoft / Framework.NETFramework / v4.0 / System.Core.dll "/ reference:" C: / Archivos de programa (x86) / Reference Assemblies / Microsoft / Framework.NETFramework / v4.0 / System.Data.DataSetExtensions.dll "/ reference:" C: / Program Files (x86) / Reference Assemblies / Microsoft / Framework.NETFramework / v4.0 / System.Data.dll "/ reference:" C: / Archivos de programa (x86) / Reference Assemblies / Microsoft / Framework.NETFramework / v4.0 / System.dll "/ reference: "C: / Archivos de programa (x86) / Referencias de referencia / Microsoft / Framework.NETFramework / v4.0 / System.Xml.dl l "/ reference:" C: / Archivos de programa (x86) / Referencias de referencia / Microsoft / Framework.NETFramework / v4.0 / System.Xml.Linq.dll "/ debug + / debug: full / filealign: 512 / Optimize- / out: obj / x86 / Debug / TestConsoleApp.exe / target: exe / utf8output Program.cs Properties / AssemblyInfo.cs "C: / Users / 105044960 / AppData / Local / Temp.NETFramework, Version = v4.0.AssemblyAttributes.cs "_CopyAppConfigFile: Se omite el objetivo" _CopyAppConfigFile "porque todos los archivos de salida están actualizados con respecto a los archivos de entrada. CopyFilesToOutputDirectory: Copiando el archivo de "obj / x86 / Debug / TestConsoleApp.exe" a "bin / Debug / TestConsoleApp.exe". TestConsoleApp -> C: / Users / 105044960 / Documents / Visual Studio 2010 / Projects / TestConsoleApp / TestConsoleApp / bin / Debug / TestConsoleApp.exe Copiando el archivo de "obj / x86 / Debug / TestConsoleApp.pdb" a "bin / Debug / TestConsoleApp .pdb ".
VS 2012:
1> CoreClean: 1> Eliminando el archivo "c: / users / 105044960 / documents / visual studio 11 / Projects / TestConsoleApp / TestConsoleApp / bin / Debug / TestConsoleApp.exe". 1> Eliminando el archivo "c: / users / 105044960 / documents / visual studio 11 / Projects / TestConsoleApp / TestConsoleApp / bin / Debug / TestConsoleApp.pdb". 1> Eliminando el archivo "c: / users / 105044960 / documents / visual studio 11 / Projects / TestConsoleApp / TestConsoleApp / obj / Debug / TestConsoleApp.csprojResolveAssemblyReference.cache". 1> Eliminando el archivo "c: / users / 105044960 / documents / visual studio 11 / Projects / TestConsoleApp / TestConsoleApp / obj / Debug / TestConsoleApp.exe". 1> Eliminando el archivo "c: / users / 105044960 / documents / visual studio 11 / Projects / TestConsoleApp / TestConsoleApp / obj / Debug / TestConsoleApp.pdb". 1> GenerateTargetFrameworkMonikerAttribute: 1> Omitir destino "GenerateTargetFrameworkMonikerAttribute" porque todos los archivos de salida están actualizados con respecto a los archivos de entrada. 1> CoreCompile: 1> C: / Windows / Microsoft.NET / Framework / v4.0.30319 / Csc.exe / noconfig / nowarn: 1701,1702,2008 / nostdlib + / platform: AnyCPU / errorreport: prompt / warn: 4 / define : DEBUG; TRACE / errorendlocation / preferreduilang: en-US / highentropyva- / reference: "C: / Archivos de programa (x86) / Referencias de referencia / Microsoft / Framework.NETFramework / v4.0 / Microsoft.CSharp.dll" / reference: "C: / Program Files (x86) / Reference Assemblies / Microsoft / Framework.NETFramework / v4.0 / mscorlib.dll" / reference: "C: / Program Files (x86) / Reference Assemblies / Microsoft / Framework.NETFramework / v4 .0 / System.Core.dll "/ reference:" C: / Archivos de programa (x86) / Reference Assemblies / Microsoft / Framework.NETFramework / v4.0 / System.Data.DataSetExtensions.dll "/ reference:" C: / Archivos de programa (x86) / Referencias de referencia / Microsoft / Framework.NETFramework / v4.0 / System.Data.dll "/ reference:" C: / Archivos de programa (x86) / Referencias de referencia / Microsoft / Framework.NETFramework / v4.0 / System.dll "/ reference:" C: / Program Files (x86) / Reference Assemblies / Microsoft / Framework.NETFr amework / v4.0 / System.Xml.dll "/ reference:" C: / Archivos de programa (x86) / Reference Assemblies / Microsoft / Framework.NETFramework / v4.0 / System.Xml.Linq.dll "/ debug + / debug : full / filealign: 512 / Optimize- /out:obj/Debug/TestConsoleApp.exe / target: exe / utf8output Program.cs Properties / AssemblyInfo.cs "C: / Users / 105044960 / AppData / Local / Temp.NETFramework, Versión = v4.0.AssemblyAttributes.cs "1> CopyFilesToOutputDirectory: 1> Copiando el archivo de" obj / Debug / TestConsoleApp.exe "a" bin / Debug / TestConsoleApp.exe ". 1> TestConsoleApp -> C: / Users / 105044960 / Documents / Visual Studio 11 / Projects / TestConsoleApp / TestConsoleApp / bin / Debug / TestConsoleApp.exe 1> Copiando el archivo de "obj / Debug / TestConsoleApp.pdb" a "bin / Debug / TestConsoleApp.pdb ".
Visual Studio usa un compilador en proceso , por lo que sabe qué versión de C # está usando.
Como notó, csc.exe desde la línea de comandos, por otro lado, usa cualquier versión de C # que esté hecha para compilar, así que en su caso será C # 5.0. Como se trata de una actualización in situ (en términos de directorio de instalación), podría romper el código que se basa en que el enlace foreach
es el mismo en todo el bucle (impar, pero posible).
NOTA: Respuesta anterior para la pregunta incorrecta: el OP sabe esto y lo estaba probando desde la línea de comandos.
La publicación de blog a la que te vinculas ya responde a tu pregunta. Creo que esta pregunta está relacionada con esta .
Es el compilador que cambió, así que esto:
foreach (int value in values)
{
// ...
}
Se utiliza para generar algo a lo largo del siguiente código:
{
int value;
for (/* iteration */)
{
value = /* get from enumerator */;
// ...
}
}
mientras que el nuevo compilador de C # ahora genera el equivalente de mover la variable al interior del bucle:
for (/* iteration */)
{
int value = /* get from enumerator */;
// ...
}
Esto hace una gran diferencia, ya que los cierres dentro del // ...
capturarán un nuevo enlace de value
en cada ciclo, en lugar de compartir el mismo enlace de value
que solía ser declarado fuera del bucle.
El problema es que, si desea que su código funcione correctamente para los compiladores más antiguos y más nuevos, debe declarar su propia variable dentro del bucle foreach
:
foreach (int value in values)
{
int newValue = value;
// ...
}
La especificación actual de C # 4.0 en Visual Studio 2010 dice:
(...) Una declaración foreach del formulario.
foreach (V v in x) embedded-statement
luego se expande a:
{ E e = ((C)(x)).GetEnumerator(); try { V v; while (e.MoveNext()) { v = (V)(T)e.Current; embedded-statement } } finally { … // Dispose e } }
La especificación C # 5.0 en Visual Studio 2012 dice:
(...) Una declaración foreach del formulario.
foreach (V v in x) embedded-statement
luego se expande a:
{ E e = ((C)(x)).GetEnumerator(); try { while (e.MoveNext()) { V v = (V)(T)e.Current; embedded-statement } } finally { … // Dispose e } }
Nota: eliminé gran parte de mi respuesta original. Estaba respondiendo a la pregunta equivocada. Una mejor respuesta sigue.
Ah, ahora veo lo que está preguntando: "¿Cómo sabe Visual Studio 2010 para compilar en C # 4 en lugar de C # 5 después de instalar .NET 4.5, incluso Visual Studio 2010 y Visual Studio 2012 usan el mismo csc.exe y pasan? ¿Las mismas opciones para eso?
@mletterle Pero .NET 4.5 es una actualización in situ de .NET 4. Así que realmente solo hay .NET 4 presente en mi máquina. La única posibilidad es que el IDE haya escondido una copia oculta del compilador .NET 4 que no puedo ver.
No estoy seguro de dónde escuchaste eso o por qué lo asumiste. .NET 4.5 NO es una actualización en el lugar. Es una versión diferente de la herramienta. Habrá diferencias. Este es uno de ellos.
Actualización 1:
Parece que estábamos usando una definición diferente de actualización "in situ". Mi uso de "in situ" es "una actualización que no debería tener diferencias perceptibles entre las versiones". La definición dada en el artículo al que lo vincula lo usa de una manera diferente: "en su lugar" en su uso es "usa el mismo CLR, pero agrega nuevas bibliotecas".
Como C # 5 es diferente de C # 4, ese cambio NO está "en su lugar" en el uso con el que estoy familiarizado.
Como resultado, la diferencia no es el CLR al que te diriges, sino la versión del idioma que estás utilizando: el CLR es una actualización "en su lugar" (tanto el 4.0 CLR), pero el idioma no es (C # 4 en VS2010 , C # 5 en VS2012.)
Actualización 2:
Dentro del archivo .csproj (que en realidad es un archivo msbuild administrado por Visual Studio), hay un atributo que especifica el marco de destino. Los proyectos realizados con Visual Studio 2012 tienen esto por defecto:
<TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
Mientras que los proyectos en Visual Studio 2010 que tienen como objetivo la versión 4 se ven así:
<TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
Esto le indica a Visual Studio que configure el entorno al compilar uno u otro marco de destino. Si bien parece que csc.exe se está invocando directamente desde un símbolo del sistema, realmente no lo es: el proyecto msbuild es en realidad lo que se está procesando, y está sucediendo en el entorno de proceso personalizado de "Visual Studio".
Solo puedo asumir los detalles de lo que está sucediendo, pero probablemente después de la actualización, tener el atributo "TargetFrameworkVersion" establecido en v4.0 devuelve el entorno a v4.0 durante la compilación de un proyecto dirigido a v4.0. Por otra parte, al invocar csc.exe desde la línea de comandos sin el entorno configurado por msbuild, utiliza los "valores predeterminados" para su versión (que ahora está predeterminada a C # 5), lo que le proporciona el nuevo comportamiento de C # 5, aunque estamos utilizando el símbolo del sistema de VS 2010. Sin embargo, cuando invoca la compilación a través de MSBuild, sabe cómo volver al entorno C # 4 original durante la duración de la compilación (dado que MSBuild también forma parte de la cadena de herramientas .NET).