自动属性初始化表达式

有过正确实现结构经验的所有 .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 Round #336 (Div. 2)B 暴力 C dp D 区间dp

    B. Hamming Distance Sum time limit per test 2 seconds memory limit per test 256 megabytes input stan ...

  2. Codeforces Round #419 (Div. 2) A B C 暴力 区间更新技巧 +前缀和 模拟

    A. Karen and Morning time limit per test 2 seconds memory limit per test 512 megabytes input standar ...

  3. php整理

    linux上安装php配套环境有些繁琐 推荐使用一键安装: https://lnmp.org/install.html phalcon框架环境: centos7下php7.0.x安装phalcon框架

  4. php 三元运算符简洁用法

    <?php header('Content-type:text;charset=utf8'); $a = 'aaaa'; $b = $a ?:'; $c = $a ? $a : '; //这个和 ...

  5. 居中div,居中浮动的元素

    定位法:position:absolute 如果子级div有定义宽和高的话就可以用这个方法.注意:margin-top,和margin-left的值均为高和宽值的一半 margin:auto法 这个也 ...

  6. [DeeplearningAI笔记]序列模型1.10-1.12LSTM/BRNN/DeepRNN

    5.1循环序列模型 觉得有用的话,欢迎一起讨论相互学习~Follow Me 1.10长短期记忆网络(Long short term memory)LSTM Hochreiter S, Schmidhu ...

  7. SPOJ DQUERY 离线树状数组+离散化

    LINK 题意:给出$(n <= 30000)$个数,$q <= 2e5$个查询,每个查询要求给出$[l,r]$内不同元素的个数 思路:这题可用主席树查询历史版本的方法做,感觉这个比较容易 ...

  8. 2015/11/3用Python写游戏,pygame入门(3):字体模块、事件显示和错误处理

    游戏里面一般是肯定会出现文字显示的,即使是俄罗斯方块也应该显示分数.那么我们应该怎样来显示文字呢,今天一起学习一下pygame的font模块. 使用字体模块 pygame可以直接调用系统字体,也可以调 ...

  9. 千里之行始于足下,node.js 资源中文导航

    响应@jiyinyiyong 号召,cnodjs 好的资源蛮多的,的确欠缺分类,在一群FAQ中,的确很容易沉下去,根据自己对node.js的理解,做成一个资源导航,PS:如果觉得合适,希望能够合并的c ...

  10. mysql查询日期相关的

    今天 select * from 表名 where to_days(时间字段名) = to_days(now()); 昨天 SELECT * FROM 表名 WHERE TO_DAYS( NOW( ) ...