网站建设图片大全,百度关键字优化价格,做网站内页图片尺寸,软件技术主修课程C# 二十年语法变迁之 C# 5 和 C# 6参考https://benbowen.blog/post/two_decades_of_csharp_ii/自从 C# 于 2000 年推出以来#xff0c;该语言的规模已经大大增加#xff0c;我不确定任何人是否有可能在任何时候都对每一种语言特性都有深入的了解。因此#xff0c;我想写一系…C# 二十年语法变迁之 C# 5 和 C# 6参考https://benbowen.blog/post/two_decades_of_csharp_ii/自从 C# 于 2000 年推出以来该语言的规模已经大大增加我不确定任何人是否有可能在任何时候都对每一种语言特性都有深入的了解。因此我想写一系列快速参考文章总结自 C# 2.0 以来所有主要的新语言特性。我不会详细介绍它们中的任何一个但我希望这个系列可以作为我自己希望你也是的参考我可以不时回过头来记住我使用的工具工具箱里有。:)开始之前的一个小提示我将跳过一些更基本的东西例如 C# 2.0 引入了泛型但它们的使用范围如此广泛以至于它们不值得包括在内而且我还可以将一些功能“粘合”在一起以使其更简洁。本系列并不打算成为该语言的权威或历史记录。相反它更像是可能派上用场的重要语言功能的“备忘单”。C# 5.0Async/await此功能是 C# 的支柱对行业产生了如此大的影响以至于它已进入其他主流语言。有无数的教程和书籍深入到这个特性但这篇文章只是作为一个快速参考指南所以我只在这里总结一下。Async/await 允许方法使用异步但以同步方式编写// async keyword tells the compiler were writing an async method
// Taskint is a Future/Promise that will eventually yield a value of type int
async Taskint GetUserAgeFromDatabase(string username) {// await keyword tells the compiler to convert this method in to a state machine at this point// Method will return the Taskint immediately at this point (assuming GetUserDetails() does not complete immediately and synchronously)// A continuation for the remainder of the method will be scheduled either on this thread (via captured context) or on task pool thread (by default) to be executed once GetUserDetails()s Task has completedvar userDetails await _databaseAccessLayer.GetUserDetails(username);// Once were here, were executing the continuationreturn userDetails.Age;
}Caller Info 属性此功能涉及可应用于可选方法参数的三个属性。然后编译器将填写详细信息这些主要用于记录static void Log(string message, [CallerMemberName] string callerMemberName null, [CallerFilePath] string callerFilePath null, [CallerLineNumber] int callerLineNumber) {Console.WriteLine(${message} (called from {callerMemberName} on line {callerLineNumber} in file {callerFilePath}));
}static void Test() {Log(My message); // Will print something like My message (called from Test() on line 15 in file C:\...\Example.cs)
}• “Caller Info 属性”C# 6.0静态导入Static Imports此功能允许在不使用类名的情况下在类上使用静态方法using static System.Console;static void Test() {WriteLine(hello); // No Console. prefix required
}• “静态导入”异常过滤器异常过滤器仅在满足某些参数时才允许捕获异常static void Test() {try {SomeOperation();}catch (Exception e) when (e.InnerException is OperationCanceledException oce) {Console.WriteLine($Operation was cancelled: {oce});}
}• “异常过滤器”不可变的自动属性此功能允许从自动属性中省略设置器以使其不可变class MyClass {public string Name { get; }public MyClass(string name) {Name name; // Can be initialized in constructor}
}• “Immutable Auto-Properties” 名称不能从构造函数以外的任何地方设置或内联请参阅下一个功能。自动属性初始化器这允许在其声明点为内联属性设置初始值class MyClass {public string Name { get; } Ben;public int Age { get; set; } 30;
}• “自动属性初始化程序”表达体成员此功能允许将某些函数体编写为单行表达式class MyClass {// Age is a read-only property; the code to the right of the is evaluated every time the property is invoked and the result of the expression is returnedpublic int Age (int) (DateTime.Now - new DateTime(1990, 01, 19)).TotalYears;// PrintAge is a method, the code to the right of the is executed when the function is invokedpublic void PrintAge() Console.WriteLine(Age);
}• “表达式主体成员” 在 C# 7.0 中添加了一些进一步的支持class MyClass {int _age;// Property getter and setterpublic int Age { get _age;set _age value 0 ?? value : throw new ArgumentOutOfRangeException(nameof(value));// Constructorpublic MyClass(int age) Age age;// Finalizer~MyClass() ResourceManager.NotifyFinalizedMyClass(this);
}• “更多表达主体的成员”空传播“Elvis”运算符如果该对象不为空则此运算符允许您访问该对象的成员或者简单地将所有值折叠为 null 否则static void PrintUserName(UserDetails? user) {Console.WriteLine($Name: {user?.Name ?? No name}, Age: {user?.Age.ToString() ?? No age});
}static void Test() {PrintUserName(new UserDetails(Ben, 30)); // Prints Name: Ben, Age: 30PrintUserName(null); // Prints Name: No name, Age: No age
}• “空条件运算符” 当将多个属性/方法/字段调用链接在一起时即var x a?.B?.C()?.D如果链中的任何单个元素为 null则整个表达式将返回 null。字符串插值和格式化字符串到目前为止这是我已经在各种示例中使用的功能。字符串插值允许以更自然的方式将变量嵌入到字符串中static void Test() {var name Ben;Console.WriteLine($My name is {name}); // The $ sign before the opening quotemark indicates this is an interpolated string
}• “基本字符串插值” 可以通过格式后缀指定值转换为字符串的方式。以下示例显示了在将浮点值转换为字符串时指定小数位数的一种方法static void Test() {var percentageComplete 12.345d;Console.WriteLine($Percentage complete: {percentageComplete:F0}%); // Prints Percentage complete: 12%Console.WriteLine($Percentage complete: {percentageComplete:F2}%); // Prints Percentage complete: 12.34%
}• “格式化字符串插值” 也可以指定对齐方式用于打印 ASCII 表static void Test() {var names new[] { Ben, Javier, Chris };var favoriteFoods new[] { Ramen, Something Vegetarian, No idea };for (var i 0; i 3; i) {Console.WriteLine($Name: {names[i],10} | Food: {favoriteFoods[i]}); // Notice the ,10 that right-aligns names to a 10-column width}
}/* Prints:* Name: Ben | Food: Ramen* Name: Javier | Food: Something Vegetarian* Name: Chris | Food: No idea
*/static void Test() {var names new[] { Ben, Javier, Chris };var favoriteFoods new[] { Ramen, Something Vegetarian, No idea };for (var i 0; i 3; i) {Console.WriteLine($Name: {names[i],-10} | Food: {favoriteFoods[i]}); // Notice the ,-10 that left-aligns names to a 10-column width}
}/* Prints:* Name: Ben | Food: Ramen* Name: Javier | Food: Something Vegetarian* Name: Chris | Food: No idea
*/• “对齐字符串插值” 对象的默认格式使用线程本地文化作为格式提供程序。有时这不是我们想要的。因此我们可以通过显式创建FormattableString然后将其转换为字符串来手动指定格式提供程序static void Test() {var percentageComplete 12.345d;FormattableString str $Percentage complete: {percentageComplete:F2}%;Console.WriteLine(str.ToString(CultureInfo.GetCultureInfo(de-DE))); // Prints Percentage complete: 12,35% (German-style number formatting)
}• “FormattableString”nameof 运算符这个小功能允许您将代码中的标记名称转换为字符串。它很有用因为它避免了在重命名这些类型时手动写出成员/类型名称的问题class User {public string Name { get; }public User(string name) {if (name null) throw new ArgumentNullException(nameof(name)); // If we rename name later this will not compile (which is good)Name name;}
}• “nameof”关联集合的替代初始化语法这是一个小功能。它允许使用更简洁的语法来初始化关联集合即主要是字典。以下两个初始化是相同的class User {static void Test() {var oldWay new Dictionaryint, string {{ 1, One },{ 2, Two },{ 3, Three },{ 4, Four }};var newWay new Dictionaryint, string {[1] One,[2] Two,[3] Three,[4] Four};}
}•“旧字典初始化与新字典初始化” 字典键和值可以是任何类型。集合初始化器的扩展“添加”方法假设您正在使用的库中定义了一个集合类型必须实现IEnumerable 但是添加元素的方法没有命名为Add(T item)。这是集合初始化器工作的要求。下面是一个使用名为UserDatabase的虚构类型的示例该类型从虚构的第三方库中实现IEnumerable static void Test() {// Wont compile// Doesnt work becuase UserDatabase calls its add method AddUser(), so we have to use the second approach belowvar database new UserDatabase {new User(Ben, 30),new User(Seb, 27),new User(Rob, 33)};// Will compile but less prettyvar database new UserDatabase();database.AddUser(new User(Ben, 30));database.AddUser(new User(Seb, 27));database.AddUser(new User(Rob, 33));
}• “尝试使用集合初始化程序时没有添加方法” 在这种情况下从 C# 6.0 开始我们可以指定Add(T item)扩展方法来启用集合初始值设定项static class UserDatabaseExtensions {public static void Add(this UserDatabase this, User u) this.AddUser(u);
}// ...static void Test() {// Hooray, this works now!var database new UserDatabase {new User(Ben, 30),new User(Seb, 27),new User(Rob, 33)};
}• “尝试使用集合初始化程序时添加扩展方法”