Cet article présente principalement le code d'implémentation simple de l'utilisation de ref et Span
1. Préface
En fait, en ce qui concerne la ref, de nombreux étudiants le savent déjà. ref est une fonctionnalité du langageC# 7.0, qui est utilisé pour le développement Personnel fournit des mécanismes pour renvoyer des variables références locales et des références de valeur. Span est également un
type de données complexe basé sur la syntaxe ref. Dans la seconde moitié de l'article, j'aurai un exemple montrant comment l'utiliser.
2. Mot-clé de référence
Qu'il s'agisse de clé de référence ou de sortie, c'est une fonctionnalité de langage difficile à comprendre et à utiliser, telle car le Regardons quelques exemples pour illustrer la similitude entre les références et les pointeurs. Bien entendu, les méthodes d'utilisation suivantes peuvent être utilisées avant C# 7.0 :public static void IncrementByRef(ref int x) { x++; } public unsafe static void IncrementByPointer(int* x) { (*x)++; }
. La fonction utilise respectivement des pointeurs ref et non safe pour compléter le paramètre +1.
int i = 30; IncrementByRef(ref i); // i = 31 unsafe{ IncrementByPointer(&i); } // i = 32
1.ref locals (référençant les variables locales)
int i = 42; ref var x = ref i; x = x + 1; // i = 43
2.ref returns (référence de valeur de retour)
ref return est une fonctionnalité puissante en C# 7. Le code suivant est le plus efficace Reflétant ses caractéristiques, cette fonction fournit une référence à un élément du tableaurenvoyée par int :
public static ref int GetArrayRef(int[] items, int index) => ref items[index];
3. Span
System.Span fait partie du noyau .Net Core, dans System.Memory.Comment l'utiliser ? Le package NuGet suivant est référencé dans le projet créé par le SDK .Net Core 2.0 :<ItemGroup> <PackageReference Include="System.Memory" Version="4.4.0-preview1-25305-02" /> <PackageReference Include="System.Runtime.CompilerServices.Unsafe" Version="4.4.0-preview1-25305-02" /> </ItemGroup>
objet Chemin. Fondamentalement, l'exploitation de pointeurs n'est pas considérée comme un bon événement sous le système .NET. Bien sûr, .NET nous fournit des références pour exploiter en toute sécurité des références à valeur unique. Mais une seule valeur ne représente qu'une petite partie des besoins de l'utilisateur en matière d'utilisation de « pointeurs » ; pour les pointeurs, la situation la plus courante est celle de l'utilisation d'une série d'« éléments » dans un espace mémoire continu.
Span est représenté comme un bloc de mémoire contigu de longueur et de type connus. À bien des égards, il est très similaire à T[] ou ArraySegment dans le sens où il fournit un accès sécurisé aux pointeurs de régions mémoire. En fait, je comprends que ce sera une abstraction du pointeur d'opération (void*) dans .NET. Les développeurs familiers avec C/C++ devraient mieux savoir ce que cela signifie.Les caractéristiques de Span sont les suivantes :
• Extrait le système de types de tous les espaces mémoire continus, y compris : les tableaux, les pointeurs non gérés, pointeurs de pile, données gérées fixes ou épinglées et références à des zones de valeurs internes•Prend en charge les types d'objets et les types de valeurs standard CLR
•Prend en charge les génériques
•Prend en charge GC, contrairement aux pointeurs qui doivent être gérés par eux-mêmes
public struct Span<T> { ref T _reference; int _length; public ref T this[int index] { get {...} } ... } public struct ReadOnlySpan<T> { ref T _reference; int _length; public T this[int index] { get {...} } ... }
chaîne</a>chaîne<code><a href="http://www.php.cn/wiki/57.html" target="_blank">string</a> content = "content-length:123",
content = "content -length: 123",Pour convertir 123 en entier, l'approche habituelle consiste d'abord à Substrpour tronquer la chaîne qui n'a rien à voir avec des caractères numériques. Le code de conversion est le suivant :
string content = "content-length:123"; Stopwatch watch1 = new Stopwatch(); watch1.Start(); for (int j = 0; j < 100000; j++) { int.Parse(content.Substring(15)); } watch1.Stop(); Console.WriteLine("\tTime Elapsed:\t" + watch1.ElapsedMilliseconds.ToString("N0") + "ms");
Pourquoi utiliser cet exemple ? Il s'agit d'un scénario typique d'utilisation d'une sous-chaîne. Chaque fois qu'une chaîne est utilisée, un nouvel objet chaîne est généré. utilisé à plusieurs reprises lors de l'exécution de int.Parse. Si un grand nombre d'opérations sont effectuées, cela exercera une pression sur le GC.
Utilisez Span pour implémenter cet algorithme :
string content = "content-length:123"; ReadOnlySpan<char> span = content.ToCharArray(); span.Slice(15).ParseToInt(); watch.Start(); for (int j = 0; j < 100000; j++) { int icb = span.Slice(15).ParseToInt(); } watch.Stop(); Console.WriteLine("\tTime Elapsed:\t" + watch.ElapsedMilliseconds.ToString("N0") + "ms");
这里将string转换为int的算法利用ReadonlySpan实现,这也是Span的典型使用场景,官方给的场景也是如些,Span适用于多次复用操作连续内存的场景。
转换代码如下:
public static class ReadonlySpanxtension { public static int ParseToInt(this ReadOnlySpan<char> rspan) { Int16 sign = 1; int num = 0; UInt16 index = 0; if (rspan[0].Equals('-')){ sign = -1; index = 1; } for (int idx = index; idx < rspan.Length; idx++){ char c = rspan[idx]; num = (c - '0') + num * 10; } return num * sign; } }
四、最后
上述两段代码100000次调用的时间如下:
String Substring Convert: Time Elapsed: 18ms ReadOnlySpan Convert: Time Elapsed: 4ms
目前Span的相关支持还够,它只是最基础架构,之后CoreFx会对很多API使用Span进行重构和实现。可见.Net Core的性能日后会越来越强大。
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!