.NET Core 2.1

.NET Core 2.1预览分层编译特性

.NET使用的JTI编译进程一直在平衡两个相互冲突的目标——更快的应用程序启动时间和更快的应用程序稳态性能。从终端用户的角度来看,如果JIT在启动时暂停并计算最佳的稳态性能,那么就会对应用程序启动速度的感受产生负面的影响。另一方面,如果JIT优先考虑更快的应用程序启动时间,那么应用程序的稳态性能就是次优的。

为了解决这一冲突,来自微软的Noah Falk宣布了面向.NET Core 2.1的分层编译。该特性使JIT执行多次编译,生成可以在运行时热交换的代码,从而获得最佳的整体性能。最终结果是应用程序启动快,同时又具有很棒的稳态性能。

由于该特性尚处于预览阶段,所以该特性还不是默认启用的,但是,对于任何.NET Core应用程序,都有几种方式可以激活。对于你能编译的应用程序,只需要向项目的默认属性组增加MSBuild属性<TieredCompilation>true</TieredCompilation>

如果你在运行一个之前编译好的应用程序,你没有源代码,那么你可以在configProperties部分的runtimeconfig.json文件中设置一个新属性:System.Runtime.TieredCompilation=true

最后,可以使用环境变量COMPlus_TieredCompilation=1启用分层编译,而不必修改任何文件。

需要注意的是,目前,该特性仍然仅限于.NET Core,不能指定用于.NET Framework部署。想要试用这项新技术的开发人员还可以查看微软在GitHub上建立的JitBench项目比较结果。

查看英文原文:.NET Core 2.1 Previews Tiered Compilation

PowerShell Core 6.0

微软发布PowerShell Core第一个版本:支持多平台开发

微软旗下的PowerShell团队正式宣布推出PowerShell Core 6.0,非常诡异的是这明明是Core的第一个版本,但是却用了一个6.0后缀。“这是我们对PowerShell做出的最大最重要的改变!”微软技术研究员兼PowerShell创始人Jeffrey Snover在Twitter上表示。

PowerShell Core 6.0

PowerShell Core基于.NET Core之上构建开源项目,可在Windows,MacOS、Linux、Ubuntu、Debian、OpenSUSE等多个平台上运行。

这也意味着现行的PowerShell分为了两个版本:基于.NET Framework的Windows PowerShell和基于.NET Core的 PowerShell Core,就微软目前的动向来看,这两个版本将会并行工作。

PowerShell(包括Windows PowerShell and PowerShell Core)是微软公司开发的任务自动化和配置管理框架,由.NET Framework和.NET Core是构建的命令行界面壳层相关脚本语言组成,最初仅Windows组件,后在2016年8月18日开源并跨平台支持,主要用户为IT 从业人员、程序员和高级数据库用户。

根据微软的博客文章,PowerShell Core将像Windows和Office 365一样定期不断更新。

.NET Core

微软跨平台.NET Core 2.0版发布

微软今天发布了.NET Core 2.0版本,属于一次非常大的版本迭代。主要更新方面,包括对两个关键组成部分Runtime(CoreCLR)和Framework Libraries(CoreFX,框架库)进行了完整的性能优化,由此可见,进程管理、JIT编译器以及服务器系统的体验将会更好。

.NET Core

 

同时,引入.NET Standard 2.0,使得开发人员可利用的API数量翻了不止两倍。

另外,微软还强调,.NET Core 2.0已经可以用于部署Azure Web应用。

据悉,.NET Core 2.0可以向下兼容.NET Core 1.0和1.1,可以并行而不会有任何冲突。

值得一提的是,今天,微软还发放了Visual Studio 2017 v15.3和Visual Studio for Mac v7.1。

.NET Core

PS:.NET Core是一个开源通用的开发框架,支持跨平台,即支持在Window,macOS,Linux等系统上的开发和部署,并且可以在硬件设备,云服务,和嵌入式/物联网方案中进行使用。.NET Core的源码放在GitHub上,由微软官方和社区共同支持。

xaml

微软正式发布XAML Standard与.NET Standard 2.0

微软在本月早些时候召开的 Build 2017 开发者大会上的披露的 XAML Standard 和 .NET Standard 2.0,现已正式发布。新工具旨在为开发者们带来“基于同一标准的跨平台 XAML 语言结构”(基于 UWP 和 Xamarin.Forms),以及基于社区反馈带来基于 .NET 的精选大集,用户们有望在“今年晚些时候”接触到 Xamarin.Forms 和 UWP 加持的 XAML 标准应用。

xaml

XAML是eXtensible Application Markup Language的英文缩写,相应的中文名称为可扩展应用程序标记语言,它是微软公司为构建应用程序用户界面而创建的一种新的描述性语言。XAML提供了一种便于扩展和定位的语法来定义和程序逻辑分离的用户界面,而这种实现方式和ASP.NET中的”代码后置”模型非常类似。XAML是一种解析性的语言,尽管它也可以被编译。它的优点是简化编程式上的用户创建过程,应用时要添加代码和配置等。

如果你对 .NET 2.0 的更感兴趣,应该不用等太长的时间,不过微软当前也没有给出更多细节。

.NET Core

微软发布 .NET Core 2.0 Preview 1

英文原文:Announcing .NET Core 2.0 Preview 1

微软在 Build 2017 大会上发布了 .NET Core 2.0 Preview 1 。

这是 .NET Core 2.0 的首次公开亮相,相比之前的版本它有很大的改进。你可以使用 Visual Studio 2017 Preview 15.3, Visual Studio for Mac 或者 VS Code 开发 .NET Core 2.0 应用程序。微软同时也发布了 ASP.NET Core 2.0 Preview 1 。

.NET Core

下载地址:

你可以在 .NET Core 2.0 Preview 1 release notes 查看此次发布的完整细节。

.NET Core 2.0 的改进

.NET Core 2.0 的进化是源于这样的愿景:

Enable you to use more of your code in more places.

  • 与 .NET Core 1.x 相比,API 增加了超过 1 倍。
  • 支持更多的 Linux 发行版
  • 在 macOS 上不再使用 OpenSSL ,改用 Apple crypto libraries
  • 支持 Live Unit Testing
  • 支持 Visual Basic
  • 支持 .Net Standard 2.0
  • Build apps that target Linux as a single operating system(以前需要指定 Linux 发行版)
.NET

.NET Framework 4.7改进了WPF和WinForms

英文原文:.NET Framework 4.7 Improves WPF and WinForms

Microsoft 新发布的 .NET Framework 4.7 中绑定了一些更新,各部分协同构成了更好的整体架构。.NET Framework 4.7 是与 Windows 10 Creator Update 一并联合发布的,着重于对 UI 的提升、对加密支持改进以及常规性能提升。Microsoft 的 Rich Lander 在宣布本次公告时指出,当前 .NET Framework 4.7 已支持.NET Standard 1.6,今年稍后交付的版本将会支持.NET Standard 2.0

net

对于运行在 Windows 10 Creators Update 上的 Windows Forms 应用,.NET Framework 4.7 支持使用高分辨率(HDPI)。但是要利用新的 HDPI 特性,开发人员必须对应用做特殊配置,启用对 HDPI 的支持。启用 HDPI 的应用将会受益于 HDPI 屏幕上更好的布局、高分辨图标的使用,并会在多个不同分辨率的监视器间移动时做出适当的行为。为有针对性地改进 Windows Forms,Lander 希望能在 GitHub 上得到一些反馈意见。

可从 HDPI 精益化中受益的控制行为包括日历控制,ListBox 控制和异常消息框。当前 Windows Forms 应用在加载后,会在分辨发生改变时做出响应,这要归功于下面三个新的事件:

  • Control.OnDpiChangedBeforeParent
  • Control.OnDpiChangedAfterParent
  • Form.DPIChanged

据 Microsoft 的 Merrie McGaw 介绍,采用 .NET Framework 4.7 的应用最终将能在 Windows 7 到 Windows 10 之间的各个版本上运行。但是使用了增强 WinForms HDPI 的应用要得到 HDPI 新特性的支持,需要运行在 Windows 10 Creators Update 上。

.NET Framework 4.7 中添加了对 WPF 触屏和手写笔的支持,这将使基于 WPF 开发的应用受益。类似于 HDPI 改进,开发人员必须要在缺省的 Windows Ink Service Platform(WISP)中选择启用此支持。.NET Framework 4.7 提供了对应用商店崩溃的自动检测,运行在 4.7 上的 ClickOne 应用将受益于此。当发生崩溃时,无需开发人员或管理员介入,ClickOne 应用将尝试自行修正问题及重新安装。

在不久的将来,Microsoft 将会提供支持旧版本 Windows 的 .NET Framework 4.7,但是并未提及何时能发布这些版本。受支持的旧版本操作系统包括 Windows 7 SP1、Windows 8,以及从 Windows Server 2008 R2 SP1 到 Windows Server 2016 间的各个版本。

包括所有改进和软件缺陷修正的完整发布说明已经提供于此,其中包括了完整的细节。

X#

X#语言加入.NET家族 将于3月17日正式上线

X# (发音为 X Sharp),一门基于 xBase 语言的开源编程语言,加入了 .NET 家族,成为一门新的 .NET 语言。未来你可以在最新版的 Visual Studio 2017 中安装和使用这门编程语言,它将在 2017 年 3 月 17 日正式上线。

X#

X# 语言的开发团队包括了前 Visual Objects 和 Vulcan.NET 开发团队的成员,包括 Fabrice Foray、Nikos Kokkalis、Chris Pyrgas 和 Robert van der Hulst 等人。

X# 是支持了多种 xBase 方言,你可以把它的核心部分看成是带 xBase 语法的C#。同时支持的 xBase 方言有 VO/Vulcan、FoxPro、dBase、Xbase++ 和 Harbour。

关于 X# 语言的更多信息可以参考 X# 在 Visual Studio Marketplace 上的 主页

相关链接:

.NET

Rider IDE恢复了对.NET Core调试的支持

英文原文:.NET Core Debugging Support Returns to Rider IDE

近期发布的 JetBrain 的 Rider IDE(EAP17)移除了对 .NET Core 调试支持。该功能与 NuGet 的一个软件包在许可上存在冲突,而 EAP17 使用 NuGet 提供的 .NET Core 项目调试功能,所以必须要移除该功能。为此,JetBrains 迅速推出了 Rider EAP18,恢复了对 .NET Core 调试的支持。

.NET

JetBrain 仅用一周时间就恢复了该功能。但是需要指出,当前 EAP18 只支持在 Windows 系统上调试 .NET Core 代码,对 Linux 和 Mac OS X 系统上调试的支持将推后发布。据 JetBrains 的 Maarten Balliauw 介绍,对 .NET Core 调试的支持中包括检查变量和单步调试代码的功能,以及加入到运行中 CoreCLR 过程的功能。

EAP18 的更新不止改进了 .NET Core 支持这一项,还增加了支持在项目中添加 COM 引用的功能。EAP18 修正了一些程序错误,其中包括解决了“无效卷分隔字符”错误,以及折叠未使用代码时功能异常的问题

JetBrains 提供了完整的修复列表,用于 Windows、Mac OS X 和 Linux 平台的 Rider EAP18 已可下载

fsharp

F# 4.1提供改善,并支持与C# 7的互操作

英文原文:F# 4.1 Brings Improvements and Interoperation with C# 7

F# 4.1对语言进行了很多改进。F# 4.1 将通过新版本的 Microsoft tools for F#提供,Microsoft tools for F#据说将于今年晚些时候发布。该版本支持结构体元组(struct tuples),与C# 7 的互操作,以及 by-ref 返回。

fsharp

由于F#的语法和类型推断简化了元组的使用,元组通常在F#中使用。它们是存储在堆栈上的引用类型。F# 4.1 中提供了存储在堆栈上的结构体元组。对于某些场景来说,性能得到了提升,比如说需要分配大量的小元组。

要支持 ValueTuple 类型,元组类型、元组表达式和元组模式可以用关键字 struct 来注释。

// Creating a new struct tuple.
let origin = struct (0, 0)

// Take struct tuples as arguments to a function and generate a new struct tuple.
let getPointFromOffset (point: struct (x, y)) (offset: struct (dx, dy)) = 
    struct (x + dx, y + dy)

// Pattern match on a struct tuple.
let doAMatch (input: struct (x, y)) =
    match input with
    | struct (0, 0) -> sprintf "The tuple is the origin!"
    | struct (_, _) -> sprintf "The tuple is NOT the origin!"

与C# 7 的互操作也支持使用 struct 关键字。

// Calls a C# function returning a value tuple
let struct(word, value) = SomeService.SomeResult ()
// Calls a C# function taking a value tuple in parameter.
let result = SomeService.CreateResult (struct("hello", 12))

  除了元组之外,记录类型和可区分联合也可以表示为值类型。它需要 struct 注释。

 [<Struct>]
 type Student = {
    Id: int
    Name: string
    Age: int
    GPA: double
    Major: string
}

[<Struct>]
type Shape = 
| Circle of radius: float
| Square of side: int
| Rectangle of sides: double*double

 

F# 4.1 也提供 by-ref 返回。F#已经支持了 ref locals,但是不支持使用或生成 byref-returning 方法。

// Returns from an array.
let f (x:int[]) = &x.[0]

// Returns from a record
[<Struct>]
type R = { mutable z : int }
let f (x:byref<R>) = &x.z

  by-ref 返回也可以在 C# 的方法中使用。

public static ref int Find (int val, int[] vals)
{
    for (int i = 0; i < vals.Length; i++)
    {
        if (vals[i] == val)
        {
            return ref numbers[i];
        }
    }
}

// 'result' is of type 'byref<int>'.
let result = SomeCSharpClass.Find (3, [| 1; 2; 3; 4; 5 |])

 

除了 GitHub 上公布的F#源代码,你也可以参考公开的语言规范获取更多信息。

Windows 10 Mobile Build 15025版本发布

昨天,微软面向Fast通道(PC端)发布了Windows 10 Build 15025版本更新,而今天微软再次推出了移动版Build 15025。相隔上个版本Build 15014已经相隔两周多的时间,因此本次版本更新添加了大量新内容。

emoji

Windows 10 Mobile Build 15025版本主要更新内容:

微软Edge浏览器可以大声朗读电子书:

同PC端相同,Edge浏览器现在能够大声阅读电子书了。用户打开任意电子书之后,点击屏幕右上角的“read aloud”按钮,就能从当前选中的行开始阅读。这项功能同样支持非商城购买的EPUB格式电子书。

支持的语言包括:ar-EG, ca-ES, da-DK, de-DE, en-AU, en-CA, en-GB, en-IN, en-US, es-ES, es-MX, fi-FI, fr-CA, fr-FR, it-IT, ja-JP, nb-NO, nl-BE, nl-NL, pt-BR, pt-PT, sv-SE, tr-TR, zh-CN.

微软Edge和emoji:

微软Edge能够显示全彩色的升级版Emoji。

emoji

在Feedback Hub中引入Collections功能:

数月以来,不断有用户反馈称有“太多重复的反馈信息”,因此今天微软宣布引入Collections功能,在Feedback Hub v16.1612.10251.0版本开始出现。

emoji

Collections会将相似的问题和反馈意见合并在一起,更加简洁的界面以及使用体验。而且通过Collections,你能够知道有多少人和你一样关注或者反馈相同的问题。

在Ease of Access设置中的全新单声道选项:

听力障碍患者使用屏幕阅读应用来阅读手机上的内容和提供相关信息,而且他们经常会使用耳机或者耳塞参加会议以及和他人对话。这个时候,他们通常使用单耳机来听取周围的声音,因此在该版本中提供了单声道设置。

.NET

.NET异常设计原则

英文原文:Designing with Exceptions in .NET

  本文要点

  • 对于常见的错误类型,优先使用内置异常及其子类;
  • 使用的异常类型要能够指示错误的来源,是应用程序本身,还是调用的库,或者是环境问题;
  • 异常类型应该可以帮助运维人员确定需要由谁首先检查错误;
  • 避免使用错误代码来区分由同一个方法引发的不相关的错误类型;
  • 永远不要捕获或抛出 ApplicationException。

异常是使用 .NET 时必然会遇到的问题,但是,有太多的开发人员没有从 API 设计的角度考虑这个问题。在大部分工作中,他们自始至终都知道需要捕获什么异常以及哪些异常需要写入全局日志。如果你设计了可以让你正确使用异常的 API,则可以显著减少修复缺陷的时间。

.NET

谁的错?

异常设计背后的基本理论始于这样一个问题,“谁的错?”为了方便本文的讨论,这个问题的答案将总是以下三者之一:

  • 应用程序
  • 环境

当我们说“库”有问题,我们是指当前执行的某个方法有内部缺陷。在这种情况下,“应用程序”是调用库方法的代码(这有点混杂难分,因为库和应用程序代码可能在相同的程序集中。)最后,“环境”是指应用程序之外一切无法控制的东西。

库缺陷

最典型的库缺陷是 NullReferenceException。对库而言,它没有任何理由抛出可以被应用程序检测到的空引用异常。如果遇到了空,则库代码应该总是抛出一个更具体的异常,说明什么为空以及如何纠正这个问题。对于参数而言,这显然是一个 ArgumentNullException 异常。而如果属性或字段为空,则 InvalidOperationException 通常更合适。

根据定义,任何表明库缺陷的异常都是该库中需要修复的 Bug。那并不是说应用程序代码没有 Bug,而是说库的 Bug 需要首先修复。只有那样,才能让应用程序开发人员知道他也犯了错误。

这样做的原因是,可能有许多人使用同样的库。如果一个人在不应该传入空的地方错误地传入了空,则其他人想必也会犯同样的错误。把 NullReferenceException 替换为一个可以清晰地显示出什么出错的异常,应用程序开发人员立即就可以知道什么出错了。

“成功之核(The Pit of Success)”

如果你读过有关 .NET 设计模式的早期文献,那么你会经常碰到短语“成功之核”。其基本思想是这样的:让代码容易被正确使用,不容易被误用,并确保异常可以告诉你哪里出错了。遵循这个 API 设计理念,几乎可以保证开发人员一开始就编写出正确的代码。

这就是为什么一个没有注释的 NullReferenceException 是如此糟糕。除了堆栈跟踪外(可能非常深入库代码),没有任何信息可以帮助开发人员确定他们哪里做错了。另一方面,ArgumentNullException 和 InvalidOperationException 则为库作者提供了一种方法,让他们可以向应用程序开发人员说明如何修复问题。

其他库缺陷

下一个库缺陷是 ArithmeticException 系列,包括 DivideByZeroException、FiniteNumberException 和 OverflowException。再次,这总是意味着库方法的内部缺陷,即使那个缺陷只是一个缺失的参数有效性检查。

库缺陷的另外一个例子是 IndexOutOfRangeException。从语义上讲,它和 ArgumentOutOfRangeException 没什么不同,参见 IList.Item,但它只适用于数组索引器。由于应用程序代码通常不会使用裸数组,所以这意味着,自定义的集合类会有 Bug。

自 .NET 2.0 引入泛型列表以来,ArrayTypeMismatchException 就很少见了。触发该异常的情况相当怪异。根据文档:

当系统无法将数组元素转换成声明的数组类型时会抛出 ArrayTypeMismatchException。例如,一个 String 类型的元素无法存入一个 Int32 数组,因为这两种类型之间无法转换。应用程序一般是不需要抛出这类异常的。

要做到这一点,前面提到的 Int32 数组必须存入一个 Object[]类型的变量。如果你使用了原始数组,则库需要对此进行检查。由于这个原因及其他许多方面的考虑,最好是不要使用原始数组,而是将它们封装到一个合适的集合类中。

通常,其他转换问题是通过 InvalidCastException 异常反映出来的。回到我们的主题,类型检查应该意味着永远不会抛出 InvalidCastException 异常,而是向调用者抛出 ArgumentException 或 InvalidOperationException 异常。

MemberAccessException 是一个基类,涵盖了各种基于反射的错误。除了直接使用反射外,COM 互操作和动态关键词的不正确使用都会触发该异常。

应用程序缺陷

典型的应用程序缺陷是 ArgumentException 及其子类 ArgumentNullException 和 ArgumentOutOfRangeException。以下是其他你可能不知道的子类:

所有这些都明确地表明应用程序有错误,而问题就出在调用库方法的行里。那条语句的两个部分都很重要。考虑下面的代码:

foo.Customer = null;
foo.Save ();

如果上述代码抛出了一个 ArgumentNullException 异常,那么应用程序开发人员会很困惑。它应该抛出一个 InvalidOperationException 异常,说明当前行之前有什么地方出了问题。

以异常为文档

典型的程序员不阅读文档,至少不会首先阅读文档。相反,他或她会阅读公共 API,编写一些代码并运行。如果代码不能正常运行,就到 Stack Overflow 上搜索异常信息。如果该程序员够幸运,则很容易在那里找到答案以及指向正确文档的链接。但即使如此,程序员们很可能也不会真正地读它。

那么,作为库作者,我们如何解决这个问题?第一步是直接将部分文档复制到异常中。

更多对象状态异常

InvalidOperationException 有一个众所周知的子类 ObjectDisposedException。它的用途显而易见,然而,很少有可销毁类会忘记抛出这个异常。如果忘记了,则常见的结果是抛出 NullReferenceException 异常。该异常是由 Dispose 方法将可销毁子对象置为空所导致的。

与 InvalidOperationException 密切相关的是 NotSupportedException 异常。这两种异常很容易区分:InvalidOperationException 是指“你现在不能那样操作”,而 NotSupportedException 是指“你永远不能对这个类做那种操作”。理论上讲,NotSupportedException 应该只在使用抽象接口时出现。

例如,一个不可变集合在遇到 IList.Add 方法时应该抛出 NotSupportedException 异常。相比之下,一个可冻结集合在冻结状态下遇到该方法时会抛出 InvalidOperationException 异常。

NotSupportedException 一个越来越重要的子类是 PlatformNotSupportedException。该异常表示,操作可以在某些运行环境里进行,但不能在其他环境里进行。例如,当将代码从 .NET 移植到 UWP 或 .NET Core 时,你可能需要使用这个异常,因为它们没有提供 .NET Framework 的所有特性。

难以捉摸的 FormatException

微软在设计 .NET 的第一个版本时犯了一些错误。例如,从逻辑上讲,FormatException 是一个参数异常类型,甚至文档也说“该异常是在参数格式无效时抛出”。但是,不管出于什么原因,它实际上没有继承 ArgumentException。它也没有地方存放参数名称。

我们暂时提供的建议是不要抛出 FormatException 异常,而是自己创建 ArgumentException 的子类,可以命名为“ArgumentFormatException”或其他效果类似的名称。这可以为你提供必要的信息,如参数名称和实际使用的值,减少调试时间。

这把我们带回了最初的主题“异常设计”。是的,当你自行开发的解析器检测到了问题,你可以只抛出一个 FormatException 异常,但那无法为想要使用你的库的应用程序开发人员提供帮助。

有关这个框架设计缺陷,另外一个例子是 IndexOutOfRangeException。从语义上讲,它和 ArgumentOutOfRangeException 没什么不同,然而,这个特例只是针对数组索引器吗?不,那样想就错了。看下 IList.Item 的实例集,该方法只会抛出 ArgumentOutOfRangeException 异常。

环境缺陷

环境缺陷源于世界并不完美这样一个事实,诸如数据宕机、Web 服务器无响应、文件丢失等场景。当 Bug 报告中出现环境缺陷时,需要考虑以下两个方面:

  1. 应用程序正确地处理了缺陷吗?
  2. 在这个环境里,是什么导致了缺陷?

通常,这会涉及人员分工。首先,应用程序开发人员应该第一个查找问题的答案。这不仅仅是说要处理错误并恢复,而且要生成一个有用的日志。

你可能想知道,为什么要从应用程序开发人员开始。应用程序开发人员要对运维团队负责。如果一次 Web 服务器调用失败,则应用程序开发人员不能只是甩手大叫“不是我的问题”。他或她首先需要确保异常提供了足够的细节信息,让运维人员可以开展他们的工作。如果异常仅仅提供了“服务器连接超时”的信息,那么他们怎么能知道涉及了哪台服务器?

专用异常

NotImplementedException

NotImplementedException 表示且仅表示一件事:这项特性还在开发过程中。因此,NotImplementedException 提供的信息应该总是包含一个任务跟踪软件的引用。例如:

throw new NotImplementedException ("参见工单#42.");

你可以提供更详细的信息,但实际上,你记录的任何信息几乎立刻就会过期。因此,最好是只将读者导向工单,他们可以在那里看到诸如该特性按计划将会在何时实现这样的信息。

AggregateException

AggregateException 是必要之恶,但很难使用。它本身不包含任何有价值的信息,所有的细节信息都隐藏在它的 InnerExceptions 集合中。

由于 AggregateException 通常只包含一个项,所以在库中将它解封装并返回真正的异常似乎是合乎逻辑的。一般来说,你不能在没有销毁原始堆栈跟踪的情况下再次抛出一个内部异常,但从 .NET 4.5 开始,该框架提供了使用 ExceptionDispatchInfo 的方法。

解封装 AggregateException

catch (AggregateException ex)
{
    if (ex.InnerExceptions.Count == 1) //解封装
        ExceptionDispatchInfo.Capture (ex.InnerExceptions[0]) .Throw ();
    else
        throw; //我们真的需要 AggregateException
}

无法回答的情况

有一些异常无法简单地纳入这个主题。例如,AccessViolationException 表示读取非托管内存时有问题。对,那可能是由原生库代码所导致的,也可能是由应用程序错误地使用了同样的代码库所导致的。只有通过研究才能揭示这个 Bug 的本质。

如果可能,你就应该在设计时避免无法回答的异常。在某些情况下,Visual Studio 的静态代码分析器甚至可以分析该规则所涵盖的标识冲突。

例如,ApplicationException 实际上已经废弃。Framework 设计指南明确指出,“不要抛出或继承 ApplicationException。”为此,应用程序不必抛出 ApplicationException 异常。虽说初衷如此,但看下下面这些子类:

  • Microsoft.JScript.BreakOutOfFinally
  • Microsoft.JScript.ContinueOutOfFinally
  • Microsoft.JScript.JScriptException
  • Microsoft.JScript.NoContextException
  • Microsoft.JScript.ReturnOutOfFinally
  • System.Reflection.InvalidFilterCriteriaException
  • System.Reflection.TargetException
  • System.Reflection.TargetInvocationException
  • System.Reflection.TargetParameterCountException
  • System.Threading.WaitHandleCannotBeOpenedException

显然,这些子类中有一些应该是参数异常,而其他的则表示环境问题。它们全都不是“应用程序异常”,因为他们只会被 .NET Framework 的库抛出。

同样的道理,开发人员不应该直接使用 SystemException。同 ApplicationException 一样,SystemException 的子类也是各不相同,包括 ArgumentException、NullReferenceException 和 AccessViolationException。微软甚至建议忘掉 SystemException 的存在,而只使用其子类。

无法回答的情况有一个子类别,就是基础设施异常。我们已经看过 AccessViolationException,以下是其他的基础设施异常:

  • CannotUnloadAppDomainException
  • BadImageFormatException
  • DataMisalignedException
  • TypeLoadException
  • TypeUnloadedException

这些异常通常很难诊断,可能会揭示出库或调用它的代码中存在的难以理解的 Bug。因此,和 ApplicationException 不同,把它们归为无法回答的情况是合理的。

实践:重新设计 SqlException

请记住这些原则,让我们看下 SqlException。除了网络错误(你根本无法到达服务器)外,在 SQL Server 的 master.dbo.sysmessages 表中有超过 11000 个不同的错误代码。因此,虽然该异常包含了你需要的所有底层信息,但是,除了简单地捕获&记录外,你实际上难以做任何事。

如果我们要重新设计 SqlException,那么我们会希望,根据我们期望用户或开发人员做什么,将其分解成多个不同的类别。

SqlClient.NetworkException 会表示所有说明数据库服务器本身之外的环境存在问题的错误代码。

SqlClient.InternalException 会包含说明服务器存在严重故障(如数据库损坏或无法访问硬盘)的错误代码。

SqlClient.SyntaxException 相当于我们的 ArgumentException。它是指你向服务器传递了糟糕的 SQL(直接或者因为 ORM 的 Bug)。

SqlClient.MissingObjectException 会在语法正确但数据库对象(表、视图、存储过程等)不存在时出现。

SqlClient.DeadlockException 出现在两个或多个进程试图修改相同的信息产生冲突时。

这些异常中的每一种都隐含着一个行动方案。

  • SqlClient.NetworkException:重试操作。如果频繁出现,则请联系运维人员。
  • SqlClient.InternalException:立即联系 DBA。
  • SqlClient.SyntaxException:通知应用程序或数据库开发人员。
  • SqlClient.MissingObjectException:请运维人员检查上一次数据库部署是否丢了东西。
  • SqlClient.DeadlockException:重试操作。如果频繁发生,则查找设计错误。

如果要在实际的工作中这样做,那么我们必须将所有 11000 多个 SQL Server 错误代码映射到那些类别中的一个,这是一项特别令人望而生畏的工作,这也就解释了为什么 SqlException 是现在这个样子。

总结

当设计 API 时,为了便于纠正问题,要将异常根据需要执行的动作的类型进行组织。这样更容易编写出自校代码,记录更准确的的日志,更快地将问题传达给合适的人或团队。

从抵触到力推,.Net Core的成功让微软正视开源

英文原文:Win-win: Open source .Net pays off for devs(By open-sourcing .Net Core, Microsoft is reaping the rewards — as are the developers)

微软在两年前做了一件当时非常令人惊讶的事情:将 .Net Core 开源。在此之前,微软曾表示开源是对软件经济的威胁。或许是为了更好的销售工具和云服务,亦或许是为了吸引更多的开发者到其平台,微软开始开源。到目前为止,这一举动已获得回报。

.net

微软已经将 .Net Core 定位为将 .Net 扩展到 Windows 之外的一种手段,跨平台版本将 .Net 的范围扩展到 MacOS 和 Linux 。微软对外合作总监 Scott Hunter 曾表示:“目前 .Net Core 的核心用户中 40% 都是新用户,这正是我们想要的。在过去一年中参与到 .Net 的开发者数量增长了 61%。 ”

虽然 .Net Core 不直接为微软创收,但却极大的给扩散了微软的影响力,并间接增长了 Azure 服务和微软其它开发工具的收入。

与此同时,开发者似乎也有受益。.Net Core 的组件包括 ASP.Net 核心框架,用于构建 Web 和云应用;.Net Core runtime 和 .Net Entity Frame,用于数据访问。ASP.Net 作为 .Net Core 1.1 版本的一部分,具有响应缓存、改进的 Azure 集成和查看重新编译等功能。微软表示 .Net Core 为速度而建,它已经比 Node.js 快八倍,比一些基准测试快三倍。

微软最近发布的 Visual Studio for Mac 也很好的预示其打算,该版本进一步推动了 .Net Core 的发展势头。微软还计划在 Visual Studio 2017 IDE 中对 .Net Core 工具进行增强,包括简化 .Net Core 项目文件的语法。

微软对开源的转变,让微软显得更加开放和“平易近人”,微软也积累了更强的社区知识。这是一个双赢,不是吗?

typescript2.1

TypeScript 2.1发布及最新功能介绍

微软今天发布TypeScript 2.1。TypeScript是一个全新的JavaScript的,能够设置静态类型,提供更好的编辑体验,强类型检测。

TypeScript是一个自由开源的编程语言,主要由于微软进行开发和维护,是基于JavaScript的严格超集,添加很多静态类型,面相对象的开发语言。

typescript2.1

新版安装需要使用NuGet,而后输入:

npm install -g typescript

第二步,你还可以使用 grab up the TypeScript 2.1 installer for Visual Studio 2015 必须在更行 Update 3. TypeScript 2.1 有一些列的改进包括 低层次的async/await 和 significantly improved inference. 更多微软功能的提供文档 TypeScript 2.1 包括:

 

  • Async Functions: 强调低层次async 功能已经可以使用! 主要代表使用 async/await ,目标 ES3/ES5不需要使用其他工具。
  • Object Rest & Spread: 我们兴奋的呈上对象的重设和传播(object rest & spread),之前此功能是一个方案,但现在TypeScript 2.1已经可以使用,而且 ES2017  中也已经提交方案。它的意义是我们能够 更好的复制,合并,挑选对象。
  • keyof and Lookup Types: 多个库添加新的对象。许多库利用的对象元素(大部分)只是一个字符串的字符串值. 鉴于TypeScript知道每一个值的属性,有一组已知的字符串(或键),你可以使用查找
  • Mapped Types
  • Partial, Readonly, Record, and Pick
  • Easier Imports

请给我们下面的评论,TypeScript 2.1 与 Visual Studio Code 或Microsoft’s Sublime Text Plugin相关内容可以查阅。

.net

.NET Core Tools转向使用MSBuild项目格式

英文原文:.NET Core Tools Switch to MSBuild

微软之前为了让 .NET Core 和 ASP.NET Core 能够支持 Windows Visual Studio 之外的开发平台,创建了基于 project.json 格式的项目系统。不过可惜,这种格式与之前的 .csproj/MSBuild 无法兼容。来自微软的 Rich Lander 近期宣布,.NET Core Tools 将在最新的 alpha 版中迁移到 MSBuild 格式。

.net.net

不过现今的 .NET Core 开发者已经在使用 project.json 格式,为了这些旧项目,微软提供了一个迁移工具(通过调用 dotnet migrate 命令),它可以把 project.json 转成 MSBuild 格式。

修改后的格式有很多好处:

  • 项目之间现在可以相互引用——现有的 .NET 标准项目(.NET Framework、Xamarin 或 UWP)和 .NET Core 之间可以相互引用
  • 项目引用和 NuGet 引用使用相同的 csproj 格式——通过 NuGet 添加的包引用会出现在 csproj 文件里
  • 在项目打开的同时可以对 csproj 文件进行修改——微软可能不认为手动修改 csproj 文件这种情况会经常发生,不过在 Visual Studio 里通过 IntelliSense 的支持来修改 csproj 文件是有可能的

在 VS2017RC(或更早版本)中打开 project.json 项目时,会弹出一个把项目单向地转成 .csproj 项目的确认对话框。要注意,这个转换是单向的,所以在确认之前要确保已经做好了备份。那些使用 .NET Core CLI Tools 的开发人员也会收到迁移到 MSBuild 的通知。Lander 说,这次发布的是一个 alpha 版本,因为它确实还不能作为正式版发布。现在可以下载到这些工具的各个平台的版本(Windows、macOS 和 Linux)。