"[Traduction] Nouvelles fonctionnalités de C# 7" consacre beaucoup d'espace à la présentation des 9 nouvelles fonctionnalités de C# 7.0. Je vais ici les présenter rapidement à travers des exemples basés sur l'expérience du projet, afin que chacun puisse les apprendre. un court laps de temps. Apprenez-en davantage à leur sujet dans le temps.
En général, ces nouvelles fonctionnalités facilitent l'écriture de code avec des idées de programmation fonctionnelle en C# 7.0. C# 6.0 a fait beaucoup de travail sur cette voie, et C# 7.0 est un pas de plus !
En C# 6.0, vous pouvez utiliser des expressions Lambda pour les méthodes membres et les propriétés en lecture seule. La chose la plus frustrante à l'époque était la raison pour laquelle l'accesseur défini de la propriété n'était pas pris en charge. . Désormais, non seulement la méthode set prend en charge les expressions Lambda, mais les constructeurs, destructeurs et index peuvent également être définis dans les expressions Lambda.
class SomeModel { private string internalValue; public string Value { get => internalValue; set => internalValue = string.IsNullOrWhiteSpace(value) ? null : value; } }
out
Variables out
Les variables sont une syntaxe qui existait auparavant. C# 7.0 lui permet simplement de regrouper la déclaration et l'utilisation pour éviter une ligne de code supplémentaire. L’effet le plus direct est que deux énoncés peuvent être complétés par une seule expression. Voici une version simplifiée de la classe Key
à titre d'exemple. Cette classe a été utilisée par nous au début pour traiter les valeurs d'ID transmises via HTTP Get/Post.
public class Key { public string Value { get; } public Key(string key) { Value = key; } public int IntValue { get { // C# 6.0,需要提前定义 intValue,但不需要初始化 // 虽然 C# 6.0 可以为只读属性使用 Lambda 表达式 // 但这里无法用一个表达式表达出来 int intValue; return int.TryParse(Value, out intValue) ? intValue : 0; } } }
Mais c'est simple en C# 7
// 注意 out var intValue, // 对于可推导的类型甚至可以用 var 来申明变量 public int IntValue => int.TryParse(Value, out var intValue) ? intValue : 0;
Les amis qui ont utilisé System.Tuple
doivent le connaîtreItem1
, Item2
Je suis profondément offensé par une dénomination aussi dénuée de sens. Cependant, C# 7.0 apporte une dénomination sémantique et réduit en même temps la création de tuples, éliminant ainsi le besoin de Tuple.Create(...)
. De plus, pour utiliser les nouvelles fonctionnalités de tuple et la déstructuration, vous devez introduire le package NuGet System.ValueTuple
.
Install-Package System.ValueTuple
Bien sûr, les tuples sont souvent utilisés pour les méthodes qui renvoient plusieurs valeurs. Certaines personnes aiment aussi utiliser les paramètres out
pour les retours, mais même si les variables out
sont désormais possibles, je ne suis toujours pas favorable à une utilisation généralisée des paramètres out
.
L'exemple de méthode suivant est utilisé pour renvoyer une plage de temps par défaut (un total de 7 jours à compter d'aujourd'hui) pour la récupération des données.
// 返回类型是一个包含两个元素的元组 (DateTime Begin, DateTime End) GetDefaultDateRange() { var end = DateTime.Today.AddDays(1); var begin = end.AddDays(-7); // 这里使用一对圆括号就创建了一个元组 return (begin, end); }
Appelez cette méthode pour obtenir un tuple. Étant donné que la valeur de retour spécifie le nom de chaque membre de données lorsqu'elle est définie, l'obtention de données à partir d'un tuple peut être sémantique. Bien sûr, vous pouvez toujours utiliser <.> et Item1
. Item2
var range = GetDefaultDateRange(); var begin = range.Begin; // 也可以 begin = range.Item1 var end = range.End; // 也可以 end = range.Item2
Cela utilise la déstructuration range
var (begin, end) = GetDefaultDateRange();
// 原来的 (DateTime Begin, DateTime End) 申明也是没问题的 (DateTime, DateTime) GetDefaultDateRange() => (DateTime.Today.AddDays(1).AddDays(-7), DateTime.Today.AddDays(1));
public class Size { public int Width { get; } public int Height { get; } public int Tall { get; } public Size(int width, int height, int tall) { this.Width = width; this.Height = height; this.Tall = tall; } // 定义成成员方法的解构 public void Deconstruct(out int width, out int height) { width = Width; height = Height; } } public static class SizeExt { // 定义成扩展方法的解构 public static void Deconstruct(this Size size, out int width, out int height, out int tall) { width = size.Width; height = size.Height; tall = size.Tall; } }
var size = new Size(1920, 1080, 10); var (w, h) = size; var (x, y, z) = size;
Size
public Size(int width, int height, int tall) => (Width, Height, Tall) = (width, height, tall);
et is
. Cela semble être un nom très noble, mais pour le dire de manière plus terre-à-terre, cela signifie juger du type et définir un type de référence spécifique. Si cela vous intéresse, vous pouvez ajouter quelques jugements supplémentaires. switch
, cela signifie définir une variable puis l'initialiser lors du jugement, donc le code écrit comme ceci is
// 假设逻辑能保证这里的 v 可能是 string 也 可能是 int string ToString(object v) { if (v is int) { int n = (int) v; return n.ToString("X4"); } else { return (string) n; } }
string ToString(object v) => (v is int n) ? n.ToString("X4") : (string) v;
Bien sûr, vous pouvez dire que la précédente peut également être simplifiée en une expression - d'accord, n'entrons pas dans ce problème, d'accord ? Je fais juste une démonstration de correspondance de modèles pourLa correspondance de motifs dans.
is
semble être beaucoup plus utile, prenons ToString comme exemple switch
static string ToString(object v) { switch (v) { case int n when n > 0xffff: // 判断类型,匹配的情况下再对值进行一个判断 return n.ToString("X8"); case int n: // 判断类型,这里 n 肯定 <= 0xffff return n.ToString("X4"); case bool b: return b ? "ON" : "OFF"; case null: return null; default: return v.ToString(); } }
dans la première branche ci-dessus Juste du bon usage. when
et out
peut presque être évitée. ref
, et l'autre est que < peut être utilisé arbitrairement dans. 🎜> Numéros de groupe. Cela ne nécessite pas de majorité, donnez juste deux exemples pour comprendre 0b
const int MARK_THREE = 0b11; // 0x03 const int LONG_MARK = 0b_1111_1111; // 0xff const double PI = 3.14_1592_6536
经常写 JavaScript 的同学肯定会深有体会,局部函数是个好东西。当然它在 C# 中带来的最大好处是将某些代码组织在了一起。我之前在项目中大量使用了 Lambda 来代替局部函数,现在可以直接替换成局部函数了。Labmda 和局部函数虽然多数情况下能做同样的事情,但是它们仍然有一些区别
对于 Lambda,编译器要干的事情比较多。总之呢,就是编译效率要低得多
Lambda 通过委托实现,调用过程比较复杂,局部函数可以直接调用。简单地说就是局部函数执行效率更高
Lambda 必须先定义再使用,局部函数可以定义在使用之后。据说这在对递归算法的支持上会有区别
比较常用的地方是 Enumerator 函数和 async 函数中,因为它们实际都不是立即执行的。
我在项目中多是用来组织代码。局部函数代替只被某一个公共 API 调用的私有函数来组织代码虽然不失为一个简化类结构的好方法,但是把公共 API 函数的函数体拉长。所以很多时候我也会使用内部类来代替某些私有函数来组织代码。这里顺便说一句,我不赞成使用 #region
组织代码。
如果和 JavaScript 中 ES2017 的 async 相比,C# 中的 Task/Task<T> 就比较像 <code>Promise
的角色。不用羡慕 JavaScript 的 async 支持 Promise like,现在 C# 的 async 也支持 Task like 了,只要实现了 GetAwaiter
方法就行。
官方提供了一个 ValueTask
作为示例,可以通过 NuGet 引入:
Install-Package System.Threading.Tasks.Extensions
这个 ValueTask
比较有用的一点就是兼容了数据类型和 Task:
string cache; ValueTask<string> GetData() { return cache == null ? new ValueTask<string>(cache) : new ValueTask<string>(GetRemoteData()); // 局部函数 async Task<string> GetRemoteData() { await Task.Delay(100); return "hello async"; } }
"[Traduction] Nouvelles fonctionnalités de C# 7" consacre beaucoup d'espace à la présentation des 9 nouvelles fonctionnalités de C# 7.0. Je vais ici les présenter rapidement à travers des exemples basés sur l'expérience du projet, afin que chacun puisse les apprendre. un court laps de temps. Apprenez-en davantage à leur sujet dans le temps.
En général, ces nouvelles fonctionnalités facilitent l'écriture de code avec des idées de programmation fonctionnelle en C# 7.0. C# 6.0 a fait beaucoup de travail sur cette voie, et C# 7.0 est un pas de plus !
En C# 6.0, vous pouvez utiliser des expressions Lambda pour les méthodes membres et les propriétés en lecture seule. La chose la plus frustrante à l'époque était la raison pour laquelle l'accesseur défini de la propriété n'était pas pris en charge. . Désormais, non seulement la méthode set prend en charge les expressions Lambda, mais les constructeurs, destructeurs et index peuvent également être définis dans les expressions Lambda.
class SomeModel { private string internalValue; public string Value { get => internalValue; set => internalValue = string.IsNullOrWhiteSpace(value) ? null : value; } }
out
Variables out
Les variables sont une syntaxe qui existait auparavant. C# 7.0 lui permet simplement de regrouper la déclaration et l'utilisation pour éviter une ligne de code supplémentaire. L’effet le plus direct est que deux énoncés peuvent être complétés par une seule expression. Voici une version simplifiée de la classe Key
à titre d'exemple. Cette classe a été utilisée par nous au début pour traiter les valeurs d'ID transmises via HTTP Get/Post.
public class Key { public string Value { get; } public Key(string key) { Value = key; } public int IntValue { get { // C# 6.0,需要提前定义 intValue,但不需要初始化 // 虽然 C# 6.0 可以为只读属性使用 Lambda 表达式 // 但这里无法用一个表达式表达出来 int intValue; return int.TryParse(Value, out intValue) ? intValue : 0; } } }
Mais c'est simple en C# 7
// 注意 out var intValue, // 对于可推导的类型甚至可以用 var 来申明变量 public int IntValue => int.TryParse(Value, out var intValue) ? intValue : 0;
Les amis qui ont utilisé System.Tuple
doivent le connaîtreItem1
, Item2
Je suis profondément offensé par une dénomination aussi dénuée de sens. Cependant, C# 7.0 apporte une dénomination sémantique et réduit en même temps la création de tuples, éliminant ainsi le besoin de Tuple.Create(...)
. De plus, pour utiliser les nouvelles fonctionnalités de tuple et la déstructuration, vous devez introduire le package NuGet System.ValueTuple
.
Install-Package System.ValueTuple
Bien sûr, les tuples sont souvent utilisés pour les méthodes qui renvoient plusieurs valeurs. Certaines personnes aiment aussi utiliser les paramètres out
pour les retours, mais même si les variables out
sont désormais possibles, je ne suis toujours pas favorable à une utilisation généralisée des paramètres out
.
L'exemple de méthode suivant est utilisé pour renvoyer une plage de temps par défaut (un total de 7 jours à compter d'aujourd'hui) pour la récupération des données.
// 返回类型是一个包含两个元素的元组 (DateTime Begin, DateTime End) GetDefaultDateRange() { var end = DateTime.Today.AddDays(1); var begin = end.AddDays(-7); // 这里使用一对圆括号就创建了一个元组 return (begin, end); }
Appelez cette méthode pour obtenir un tuple. Étant donné que la valeur de retour spécifie le nom de chaque membre de données lorsqu'elle est définie, l'obtention de données à partir d'un tuple peut être sémantique. Bien sûr, vous pouvez toujours utiliser <.> et Item1
. Item2
var range = GetDefaultDateRange(); var begin = range.Begin; // 也可以 begin = range.Item1 var end = range.End; // 也可以 end = range.Item2
Cela utilise la déstructuration range
var (begin, end) = GetDefaultDateRange();
// 原来的 (DateTime Begin, DateTime End) 申明也是没问题的 (DateTime, DateTime) GetDefaultDateRange() => (DateTime.Today.AddDays(1).AddDays(-7), DateTime.Today.AddDays(1));
public class Size { public int Width { get; } public int Height { get; } public int Tall { get; } public Size(int width, int height, int tall) { this.Width = width; this.Height = height; this.Tall = tall; } // 定义成成员方法的解构 public void Deconstruct(out int width, out int height) { width = Width; height = Height; } } public static class SizeExt { // 定义成扩展方法的解构 public static void Deconstruct(this Size size, out int width, out int height, out int tall) { width = size.Width; height = size.Height; tall = size.Tall; } }
var size = new Size(1920, 1080, 10); var (w, h) = size; var (x, y, z) = size;
Size
public Size(int width, int height, int tall) => (Width, Height, Tall) = (width, height, tall);
et is
. Cela semble être un nom très noble, mais pour le dire de manière plus terre-à-terre, cela signifie juger du type et définir un type de référence spécifique. Si cela vous intéresse, vous pouvez ajouter quelques jugements supplémentaires. switch
, cela signifie définir une variable puis l'initialiser lors du jugement, donc le code écrit comme ceci is
// 假设逻辑能保证这里的 v 可能是 string 也 可能是 int string ToString(object v) { if (v is int) { int n = (int) v; return n.ToString("X4"); } else { return (string) n; } }
string ToString(object v) => (v is int n) ? n.ToString("X4") : (string) v;
Bien sûr, vous pouvez dire que la précédente peut également être simplifiée en une expression - d'accord, n'entrons pas dans ce problème, d'accord ? Je fais juste une démonstration de correspondance de modèles pourLa correspondance de motifs dans.
is
semble être beaucoup plus utile, prenons ToString comme exemple switch
static string ToString(object v) { switch (v) { case int n when n > 0xffff: // 判断类型,匹配的情况下再对值进行一个判断 return n.ToString("X8"); case int n: // 判断类型,这里 n 肯定 <= 0xffff return n.ToString("X4"); case bool b: return b ? "ON" : "OFF"; case null: return null; default: return v.ToString(); } }
dans la première branche ci-dessus Juste du bon usage. when
et out
peut presque être évitée. ref
, et l'autre est que < peut être utilisé arbitrairement dans. 🎜> Numéros de groupe. Cela ne nécessite pas de majorité, donnez juste deux exemples pour comprendre 0b
const int MARK_THREE = 0b11; // 0x03 const int LONG_MARK = 0b_1111_1111; // 0xff const double PI = 3.14_1592_6536
经常写 JavaScript 的同学肯定会深有体会,局部函数是个好东西。当然它在 C# 中带来的最大好处是将某些代码组织在了一起。我之前在项目中大量使用了 Lambda 来代替局部函数,现在可以直接替换成局部函数了。Labmda 和局部函数虽然多数情况下能做同样的事情,但是它们仍然有一些区别
对于 Lambda,编译器要干的事情比较多。总之呢,就是编译效率要低得多
Lambda 通过委托实现,调用过程比较复杂,局部函数可以直接调用。简单地说就是局部函数执行效率更高
Lambda 必须先定义再使用,局部函数可以定义在使用之后。据说这在对递归算法的支持上会有区别
比较常用的地方是 Enumerator 函数和 async 函数中,因为它们实际都不是立即执行的。
我在项目中多是用来组织代码。局部函数代替只被某一个公共 API 调用的私有函数来组织代码虽然不失为一个简化类结构的好方法,但是把公共 API 函数的函数体拉长。所以很多时候我也会使用内部类来代替某些私有函数来组织代码。这里顺便说一句,我不赞成使用 #region
组织代码。
如果和 JavaScript 中 ES2017 的 async 相比,C# 中的 Task/Task<T> 就比较像 <code>Promise
的角色。不用羡慕 JavaScript 的 async 支持 Promise like,现在 C# 的 async 也支持 Task like 了,只要实现了 GetAwaiter
方法就行。
官方提供了一个 ValueTask
作为示例,可以通过 NuGet 引入:
Install-Package System.Threading.Tasks.Extensions
这个 ValueTask
比较有用的一点就是兼容了数据类型和 Task:
string cache; ValueTask<string> GetData() { return cache == null ? new ValueTask<string>(cache) : new ValueTask<string>(GetRemoteData()); // 局部函数 async Task<string> GetRemoteData() { await Task.Delay(100); return "hello async"; } }
Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!