C# 6.0适用于.NET 4.0吗?

276

我创建了一个示例项目,以C#6.0的新特性 - 空值传播和属性初始化为例,将目标版本设置为.NET 4.0,结果...它可以工作。

public class Cat
{
    public int TailLength { get; set; } = 4;

    public Cat Friend { get; set; }

    public string Mew() { return "Mew!"; }
}

class Program
{
    static void Main(string[] args)
    {
        var cat = new Cat {Friend = new Cat()};
        Console.WriteLine(cat?.Friend.Mew());
        Console.WriteLine(cat?.Friend?.Friend?.Mew() ?? "Null");
        Console.WriteLine(cat?.Friend?.Friend?.TailLength ?? 0);
    }
}

这是否意味着我可以在针对.NET 4.0的软件中使用C# 6.0功能?是否有任何限制或缺点?


7
.NET 2.0 到 3.5 版本使用 CLR v2.0,更新的版本使用 CLR v4.0。 - i3arnon
请记住,优化时:您正在为每只猫添加单独的if-null-check。 - Terence
2
我的天啊。我一直在开发一个针对v4.6的WCF,结果被“提醒”生产服务器要等到2018年才能升级。我以为一个月的工作需要几天的重构。结果只用了五分钟就完成了。谢谢你,微软!:D - Eric Wu
5个回答

288

是的(大多数情况下)。C#6.0需要新的Roslyn编译器,但新编译器可以编译针对旧框架版本的代码。这仅限于不需要来自框架支持的新功能。

例如,尽管在较早的.Net版本中可以使用C#6.0的字符串内插特性(因为它会导致调用string.Format),但在旧框架版本中无法使用需要框架支持的其他新特性。

int i = 3;
string s = $"{i}";
您需要 .Net 4.6 才能将其与 IFormattable 一起使用,因为只有新的框架版本才添加了 System.FormattableString
int i = 3;
IFormattable s = $"{i}";
你提到的这些情况不需要来自框架的类型才能运行。因此,编译器完全能够支持旧框架版本的这些功能。

33
实际上,您不需要 .Net 4.6,只需要其中添加的一些类型。 您可以自己将这些类型添加到旧框架中。[此代码可在 .Net 4.0 和 3.5 上正常运行。] (https://gist.github.com/svick/e5b30f73146a501cc64f) - svick
10
有没有一个列表可以查看哪些C#6功能在.NET 4.0中可用?另一种问法是:哪些新功能需要框架支持,哪些不需要? - Rubenisme
1
@Rubenisme,除了“IFormattable字符串插值法”之外,我想不出其他的了。 - i3arnon
3
我想我们可以说所有的语法糖都可以被使用并针对旧的框架版本。这样说可以吗? - mkb
5
“是的,‘Syntactic sugar’指的就是那些只依赖于编译器能力而非框架能力的特性。” - i3arnon
显示剩余6条评论

52

本文旨在重点讲解如何理解维基百科和其他链接。

当维基百科说C# 6.0附带.NET Framework 4.6时,它只是意味着编译器(msc.exe)的生产版本将成为.NET Framework 4.6发布的一部分。通过多重目标,这样的编译器可以支持较低版本的.NET Framework版本。当然,自Roslyn成为开源项目以来,编译器现在完全是一个单独的组件。

当某个东西引用CLR版本为4.0.30319(.0)时,实际上可以是.NET Framework 4.*(4.0、4.0.*、4.5、4.5.*、4.6、4.6.*),因为它们都实现了CLR版本4规范。更不用说Xamarin/Mono也实现了相同的CLR规范。

虽然MSDN页面尚未完全更新,但一些页面已经在版本信息部分列出了.NET Framework 4.6。

总的来说,语言规范(以及C#编译器)、CLR规范和.NET Framework发布不是紧密耦合的。它确实为开发人员提供了足够的灵活性,以利用新编译器来针对旧的CLR和.NET Framework。


30

是的,您可以使用更新的编译器来编译旧的框架,并获得新的编译器功能(前提是这些功能不需要在.NET 4.6中引入的新类型)。

另一个例子是具有默认参数的方法是在C# 4.0(.NET 4.0)中引入的,但您可以在.NET 2.0(C# 2.0)和.NET 3.5(C# 3.0)项目中使用它们。

您还可以在.NET 2.0或.NET 3.0中使用扩展方法(在C# 3.0中引入),如果进行一些小的变通以使编译器能够找到在.NET 3.5中引入的属性。


1

@oobe的回答实际上很重要。在使用C:\Program Files (x86)\MSBuild\14.0\Bin中的MSBuild.exe后,我可以仅通过批处理文件构建我的解决方案。


1
如果您正在使用构建脚本,请记得将路径更改为新的生成器:
设置 CPATH=C:\Program Files (x86)\MSBuild\14.0\Bin。

[Rebuild.bat]

set CPATH=C:\Program Files (x86)\MSBuild\14.0\Bin
call nuget_restore.bat
"%CPATH%\msbuild" YourSolution.sln /t:Rebuild /p:Configuration=Release /fileLogger /flp:logfile=JustErrors.log;errorsonly /verbosity:minimal

if %errorlevel% neq 0 goto ERROR

REM call deploy Release  //Things like deploy files..
goto END

:ERROR
       echo ERROR: %errorlevel%
       pause

:END

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接