自动属性初始化表达式

有过正确实现结构经验的所有 .NET 开发人员无疑都为一个问题所困扰:需要使用多少语法才能使类型固定不变(为 .NET 标准建议的类型)。此问题实际上是只读属性存在的问题:

  1. 定义为只读的支持字段
  2. 构造函数内支持字段的初始化
  3. 属性的显式实现(而非使用自动属性)
  4. 返回支持字段的显式 getter 实现

所有这一切仅仅是为了“正确地”实现固定不变的属性。之后,此情况还会针对类型的所有属性重复发生。因此,正确操作需要比不堪一击的方法付出明显更多的努力。发布了自动属性初始化表达式(CTP3 还包括对初始化表达式的支持)这个新功能后,C# 6.0 就可派上用场了。自动属性初始化表达式允许直接在属性的声明内分配属性。对于只读属性,它负责确保属性固定不变所需的所有繁琐程序。例如,请看本示例中的 FingerPrint 类:

public class FingerPrint
{
public DateTime TimeStamp { get; } = DateTime.UtcNow;
public string User { get; } =
System.Security.Principal.WindowsPrincipal.Current.Identity.Name;
public string Process { get; } =
System.Diagnostics.Process.GetCurrentProcess().ProcessName;
}

如代码所示,属性初始化表达式允许向属性分配一个初始值作为属性声明的一部分。属性可以是只读的(只包含 getter),也可以是读/写(包含 setter 和 getter)的。如果是只读的,则基础支持字段将通过只读修饰符自动声明。这就确保了在初始化之后会固定不变。

初始化表达式可以是任意表达式。例如,通过使用条件运算符,您可以设置默认初始化值:

public string Config { get; } = string.IsNullOrWhiteSpace(
string connectionString =
(string)Properties.Settings.Default.Context?["connectionString"])?
connectionString : "<none>";

本示例中,请注意之前的文章中所讨论的如何使用声明表达式(请参阅 itl.tc/?p=4040)。如果您需要的不只是表达式,可以将初始化重构到静态方法中,然后对其进行调用。

Nameof 表达式

CTP3 版本中介绍的另一个新增功能是支持 nameof 表达式。您将多次需要在代码中使用“魔幻字符串”。此类“魔幻字符串”是映射到您代码中的程序元素的普通 C# 字符串。例如,引发 ArgumentNullException 时,使用一个字符串表示无效对应参数的名称。遗憾的是,这些魔幻字符串未经过编译时验证,任意程序元素更改(例如,重命名参数)都不会自动更新魔幻字符串,从而导致不一致,而编译器根本不会发现此问题。

在其他情况下,例如引发 OnPropertyChanged 事件时,可以通过提取名称的树表达式技术避免出现魔幻字符串。鉴于操作简单(只识别程序元素名称),所以这或许有点让人头疼。无论哪种情况,解决方案都不太理想。

若要解决这一特性,C# 6.0 提供了对“程序元素”名称的访问权限,无论是类名称、方法名称、参数名称还是特定属性名称(可能是对于使用反射的情况)。例如,图 2 中的代码使用 nameof 表达式提取参数的名称。

//使用 Nameof 表达式提取参数名称

void ThrowArgumentNullExceptionUsingNameOf(string param1)
{
throw new ArgumentNullException(nameof(param1));
}
[TestMethod]
public void NameOf_UsingNameofExpressionInArgumentNullException()
{
try
{
ThrowArgumentNullExceptionUsingNameOf("data");
Assert.Fail("This code should not be reached");
}
catch (ArgumentNullException exception)
{
Assert.AreEqual<string>("param1", exception.ParamName);
}

正如测试方法所演示的,ArgumentNullException 的 ParamName 属性具有 param1 值,这是使用方法中的 nameof(param1) 表达式的值集。Nameof 表达式不仅仅用于参数,您还可以使用它来检索所有编程元素。

//检索其他编程元素

namespace CSharp6.Tests
{
[TestClass]
public class NameofTests
{
[TestMethod]
public void Nameof_ExtractsName()
{
Assert.AreEqual<string>("NameofTests", nameof(NameofTests));
Assert.AreEqual<string>("TestMethodAttribute",
nameof(TestMethodAttribute));
Assert.AreEqual<string>("TestMethodAttribute",
nameof(
Microsoft.VisualStudio.TestTools.UnitTesting.TestMethodAttribute));
Assert.AreEqual<string>("Nameof_ExtractsName",
string.Format("{0}", nameof(Nameof_ExtractsName)));
Assert.AreEqual<string>("Nameof_ExtractsName",
string.Format("{0}", nameof(
CSharp6.Tests.NameofTests.Nameof_ExtractsName)));
}
}
}

Nameof 表达式仅检索最终的标识符,即使您使用更多的显式包含点的名称也是如此。此外,对于属性而言,未隐含“Attribute”后缀。相反,编译需要它。它非常适合用于清理混乱代码。

原文出处:http://msdn.microsoft.com/zh-cn/magazine/dn802602.aspx

C# 6.0 新特性 (二)的更多相关文章

  1. C++2.0新特性(二)——<一致性初始化、Initializer_list 、for循环、explicit>

    一.一致性初始化(uniform initialization) 之前初始化时存在多个版本,让使用者使用时比较混乱,现在提供一种万用的初始化方法,就是使用大括号. 原理解析:当编译器看到大括号包起来的 ...

  2. c# 6.0新特性(二)

    写在前面 上篇文章介绍了c#6.0的using static,Auto Property Initializers,Index Initializers新的特性,这篇文章将把剩下的几个学习一下. 原文 ...

  3. 浅谈Tuple之C#4.0新特性那些事儿你还记得多少?

    来源:微信公众号CodeL 今天给大家分享的内容基于前几天收到的一条留言信息,留言内容是这样的: 看了这位网友的留言相信有不少刚接触开发的童鞋们也会有同样的困惑,除了用新建类作为桥梁之外还有什么好的办 ...

  4. C#发展历程以及C#6.0新特性

    一.C#发展历程 下图是自己整理列出了C#每次重要更新的时间及增加的新特性,对于了解C#这些年的发展历程,对C#的认识更加全面,是有帮助的. 二.C#6.0新特性 1.字符串插值 (String In ...

  5. [转]Servlet 3.0 新特性详解

    原文地址:http://blog.csdn.net/xiazdong/article/details/7208316 Servlet 3.0 新特性概览 1.Servlet.Filter.Listen ...

  6. [C#]6.0新特性浅谈

    原文:[C#]6.0新特性浅谈 C#6.0出来也有很长一段时间了,虽然新的特性和语法趋于稳定,但是对于大多数程序猿来说,想在工作中用上C#6.0估计还得等上不短的一段时间.所以现在再来聊一聊新版本带来 ...

  7. 腾讯云安全:开发者必看|Android 8.0 新特性及开发指南

    欢迎大家关注腾讯云技术社区-博客园官方主页,我们将持续在博客园为大家推荐技术精品文章哦~ 背景介绍 谷歌2017 I/O开发者大会今年将于5月17-19日在美国加州举办.大会将跟往年一样发布最新的 A ...

  8. Android Oreo 8.0 新特性实战 Autosizing TextView --自动缩放TextView

    Android Oreo 8.0 新特性实战 Autosizing TextView --自动缩放TextView 8.0出来很久了,这个新特性已经用了很久了,但是一直没有亲自去试试.这几天新的需求来 ...

  9. Django 2.0 新特性 抢先看!

    一.Python兼容性 Django 2.0支持Python3.4.3.5和3.6.Django官方强烈推荐每个系列的最新版本. 最重要的是Django 2.0不再支持Python2! Django ...

随机推荐

  1. Codeforces 895.E Eyes Closed

    E. Eyes Closed time limit per test 2.5 seconds memory limit per test 256 megabytes input standard in ...

  2. Codeforces 894.E Ralph and Mushrooms

    E. Ralph and Mushrooms time limit per test 2.5 seconds memory limit per test 512 megabytes input sta ...

  3. Java面试题:多继承

    招聘和面试对开发经理来说是一个无尽头的工作,虽然有时你可以从HR这边获得一些帮助,但是最后还是得由你来拍板,或者就像另一篇文章"Java 面试题:写一个字符串的反转"所说: 面试开 ...

  4. [DeeplearningAI笔记]序列模型2.7负采样Negative sampling

    5.2自然语言处理 觉得有用的话,欢迎一起讨论相互学习~Follow Me 2.7 负采样 Negative sampling Mikolov T, Sutskever I, Chen K, et a ...

  5. codeblocks快捷键(转)

    ==日常编辑== • 按住Ctrl滚滚轮,代码的字体会随你心意变大变小.• 在编辑区按住右键可拖动代码,省去拉(尤其是横向)滚动条之麻烦:相关设置:Mouse Drag Scrolling.• Ctr ...

  6. ArrayList既然继承自AbstractList抽象类,而AbstractList已经实现了List接口,那么ArrayList类为何还要再实现List接口呢?

    https://www.cnblogs.com/bluejavababy/p/4320545.html

  7. javaScript基础语法介绍

    简介 JavaScript是一种脚本语言. (脚本,一条条的文字命令.执行时由系统的一个解释器,将其一条条的翻译成机器可识别的指令,然后执行.常见的脚本:批处理脚本.T-SQL脚本.VBScript等 ...

  8. JavaScript:自动生成博文目录导航

    感谢 孤傲苍狼 分享了 自动生成博文目录的方法,本文仅作存档使用. 图 1:效果预览 CSS 样式 #TOCbar{ font-size:12px; text-align:left; position ...

  9. 树形DP初探•总结

    这几天,我自学了基础的树形DP,在此给大家分享一下我的心得.   首先,树形DP这种题主要就是解决有明确分层次且无环的树上动态规划的题.这种题型一般(注意只是基础.普通的情况下)用深度优先搜索来解决实 ...

  10. flex实例(阮一峰)

    Flex 布局教程:实例篇   作者: 阮一峰 日期: 2015年7月14日 上一篇文章介绍了Flex布局的语法,今天介绍常见布局的Flex写法. 你会看到,不管是什么布局,Flex往往都可以几行命令 ...