为什么 VS 2010 中构建的应用程序与 VS 2010 中构建的应用程序的行为存在差异? VS 2012?

2024-05-01

我正在检查在我们的构建机器上安装 .NET 4.5 是否会更改 VS 2010 生成的输出 IL 映像。

因为我知道 .NET 4.5 中 foreach 的行为已发生变化,以避免由于以下原因而出现问题访问修改后的关闭 http://blogs.msdn.com/b/ericlippert/archive/2009/11/12/closing-over-the-loop-variable-considered-harmful.aspx,我选择了一个展示该行为的简单应用程序。

  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);
        }

VS 2010 输出: 666

VS 2012 输出: 456

我在 VS 2010 中创建了一个控制台应用程序,并在 VS 2012 中创建了一个具有相同代码的控制台应用程序(两者都针对 .NET 4)。

但是,这两个控制台应用程序根据构建它们所使用的 IDE 表现出不同的行为。在构建输出中,我检查了两者的构建参数几乎相似。所以我想知道最终的可执行文件如何表现出不同的行为? .NET 4.5 是就地升级,因此两个 IDE 的编译器必须相同。

注意:我确实看过一个相关问题:VS 2010 和 VS 2012 中的不同 LINQ 答案 https://stackoverflow.com/questions/13327224/different-linq-answer-in-vs-2010-and-vs-2012但它没有回答我关于为什么可执行行为不同的问题。

EDIT 1: As 姆莱特莱 https://stackoverflow.com/users/65235/mletterle提到过,我确实尝试在 VS 2010 命令提示符下使用 VS 2010 输出窗口中的命令行构建代码。生成的输出的行为就像是使用 VS 2012 构建的一样。

EDIT 2:

我正在发布输出窗口中的输出:

VS 2010:构建于 2012 年 12 月 20 日晚上 11:04:56 开始。

CoreClean:创建目录“obj\x86\Debug\”。 GenerateTargetFrameworkMonikerAttribute:跳过目标 “GenerateTargetFrameworkMonikerAttribute”,因为所有输出文件都是 输入文件是最新的。核心编译:
C:\Windows\Microsoft.NET\Framework\v4.0.30319\Csc.exe /noconfig /nowarn:1701,1702 /nostdlib+ /platform:x86 /errorreport:提示 /warn:4 /define:DEBUG;TRACE /errorendlocation /preferreduilang:en-US /highentropyva- /reference:"C:\Program Files (x86)\Reference 程序集\Microsoft\Framework.NETFramework\v4.0\Microsoft.CSharp.dll” /reference:"C:\Program Files (x86)\Reference 程序集\Microsoft\Framework.NETFramework\v4.0\mscorlib.dll” /reference:"C:\Program Files (x86)\Reference 程序集\Microsoft\Framework.NETFramework\v4.0\System.Core.dll” /reference:"C:\Program Files (x86)\Reference 程序集\Microsoft\Framework.NETFramework\v4.0\System.Data.DataSetExtensions.dll” /reference:"C:\Program Files (x86)\Reference 程序集\Microsoft\Framework.NETFramework\v4.0\System.Data.dll” /reference:"C:\Program Files (x86)\Reference 程序集\Microsoft\Framework.NETFramework\v4.0\System.dll” /reference:"C:\Program Files (x86)\Reference 程序集\Microsoft\Framework.NETFramework\v4.0\System.Xml.dll” /reference:"C:\Program Files (x86)\Reference 程序集\Microsoft\Framework.NETFramework\v4.0\System.Xml.Linq.dll” /调试+ /调试:完整/文件对齐:512 /优化- /out:obj\x86\Debug\TestConsoleApp.exe /target:exe /utf8output Program.cs 属性\AssemblyInfo.cs “C:\ Users \ 105044960 \ AppData \ Local \ Temp.NETFramework,版本= v4.0.AssemblyAttributes.cs” _CopyAppConfigFile:跳过目标“_CopyAppConfigFile”,因为所有输出文件相对于输入文件都是最新的。 CopyFilesToOutputDirectory:从以下位置复制文件 “obj\x86\Debug\TestConsoleApp.exe”到“bin\Debug\TestConsoleApp.exe”。 TestConsoleApp -> C:\Users\105044960\Documents\Visual Studio 2010\项目\TestConsoleApp\TestConsoleApp\bin\调试\TestConsoleApp.exe 将文件从“obj\x86\Debug\TestConsoleApp.pdb”复制到 “bin\Debug\TestConsoleApp.pdb”。

VS 2012:

1>CoreClean: 1> 删除文件“c:\users\105044960\documents\visual 工作室 11\Projects\TestConsoleApp\TestConsoleApp\bin\Debug\TestConsoleApp.exe”。 1> 删除文件“c:\users\105044960\documents\visual studio 11\Projects\TestConsoleApp\TestConsoleApp\bin\Debug\TestConsoleApp.pdb”。 1> 删除文件“c:\users\105044960\documents\visual studio 11\Projects\TestConsoleApp\TestConsoleApp\obj\Debug\TestConsoleApp.csprojResolveAssemblyReference.cache”。 1> 删除文件“c:\users\105044960\documents\visual studio 11\Projects\TestConsoleApp\TestConsoleApp\obj\Debug\TestConsoleApp.exe”。 1> 删除文件“c:\users\105044960\documents\visual studio 11\Projects\TestConsoleApp\TestConsoleApp\obj\Debug\TestConsoleApp.pdb”。 1>GenerateTargetFrameworkMonikerAttribute: 1>跳过目标 “GenerateTargetFrameworkMonikerAttribute”,因为所有输出文件都是 输入文件是最新的。 1>核心编译:1> C:\Windows\Microsoft.NET\Framework\v4.0.30319\Csc.exe /noconfig /nowarn:1701,1702,2008 /nostdlib+ /platform:AnyCPU /errorreport:提示 /warn:4 /define:DEBUG;TRACE /errorendlocation /preferreduilang:en-US /highentropyva- /reference:"C:\Program Files (x86)\Reference 程序集\Microsoft\Framework.NETFramework\v4.0\Microsoft.CSharp.dll” /reference:"C:\Program Files (x86)\Reference 程序集\Microsoft\Framework.NETFramework\v4.0\mscorlib.dll” /reference:"C:\Program Files (x86)\Reference 程序集\Microsoft\Framework.NETFramework\v4.0\System.Core.dll” /reference:"C:\Program Files (x86)\Reference 程序集\Microsoft\Framework.NETFramework\v4.0\System.Data.DataSetExtensions.dll” /reference:"C:\Program Files (x86)\Reference 程序集\Microsoft\Framework.NETFramework\v4.0\System.Data.dll” /reference:"C:\Program Files (x86)\Reference 程序集\Microsoft\Framework.NETFramework\v4.0\System.dll” /reference:"C:\Program Files (x86)\Reference 程序集\Microsoft\Framework.NETFramework\v4.0\System.Xml.dll” /reference:"C:\Program Files (x86)\Reference 程序集\Microsoft\Framework.NETFramework\v4.0\System.Xml.Linq.dll” /调试+ /调试:完整/文件对齐:512 /优化- /out:obj\Debug\TestConsoleApp.exe /target:exe /utf8output Program.cs 属性\AssemblyInfo.cs “C:\ Users \ 105044960 \ AppData \ Local \ Temp.NETFramework,版本= v4.0.AssemblyAttributes.cs” 1>CopyFilesToOutputDirectory: 1> 从以下位置复制文件 “obj\Debug\TestConsoleApp.exe”到“bin\Debug\TestConsoleApp.exe”。 1> TestConsoleApp -> C:\Users\105044960\Documents\Visual Studio 11\项目\TestConsoleApp\TestConsoleApp\bin\Debug\TestConsoleApp.exe 1> 将文件从“obj\Debug\TestConsoleApp.pdb”复制到 “bin\Debug\TestConsoleApp.pdb”。


注:我删除了大部分原来的回复。它回答了错误的问题。接下来是更好的回应。

啊,现在我明白你在问什么了:“安装 .NET 4.5 后,Visual Studio 2010 如何知道编译为 C# 4 而不是 C# 5,甚至 Visual Studio 2010 和 Visual Studio 2012 使用相同的 csc.exe 并通过相同的选项吗?”

@mletterle 但是 .NET 4.5 是 .NET 4 的就地升级。所以我的机器上实际上只有 .NET 4。唯一的可能性是 IDE 隐藏了我看不到的 .NET 4 编译器的隐藏副本。

我不确定你从哪里听说的,也不知道你为什么这么认为。 .NET 4.5 不是就地升级。这是该工具的不同版本。会有差异。这是其中之一。

更新1:

看起来我们使用了“就地”升级的不同定义。我对“就地”的用法是“版本之间不应有明显差异的升级”。中给出的定义您链接到的文章 http://www.hanselman.com/blog/NETVersioningAndMultiTargetingNET45IsAnInplaceUpgradeToNET40.aspx以不同的方式使用它:“就地”的用法是“使用相同的 CLR,但添加新的库”。

由于 C# 5 与 C# 4 不同,因此在我熟悉的用法中该更改并未“就位”。

因此,区别不在于您所针对的 CLR,而在于您使用的语言版本 - CLR 是“就地”升级(均为 4.0 CLR),但语言不是(VS2010 中的 C# 4) ,VS2012 中的 C#5。)

更新2:

在 .csproj 文件(实际上是由 Visual Studio 管理的 msbuild 文件)中,有一个指定目标框架的属性。使用 Visual Studio 2012 制作的项目默认具有以下内容:

<TargetFrameworkVersion>v4.5</TargetFrameworkVersion>

而 Visual Studio 2010 中针对版本 4 的项目如下所示:

<TargetFrameworkVersion>v4.0</TargetFrameworkVersion>

这告诉 Visual Studio 在构建一个或另一个目标框架时设置环境。虽然看起来 csc.exe 是直接从命令提示符调用的,但实际上并非如此:msbuild 项目实际上正在处理,并且它发生在“Visual Studio”的自定义处理环境中。

我只能假设发生的情况的具体情况,但很可能在升级后,将“TargetFrameworkVersion”属性设置为 v4.0 会在编译针对 v4.0 的项目期间将环境返回到 v4.0。另一方面,通过在没有 msbuild 设置环境的情况下从命令行调用 csc.exe,它会使用其版本的“默认值”(现在默认为 C# 5),从而为您提供新的 C# 5 行为,即使您正在使用 VS 2010 命令提示符。不过,当您通过 MSBuild 调用构建时,它知道如何在构建期间返回原始 C# 4 环境(因为 MSBuild 也是 .NET 工具链的一部分。)

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

为什么 VS 2010 中构建的应用程序与 VS 2010 中构建的应用程序的行为存在差异? VS 2012? 的相关文章

随机推荐