Maison >développement back-end >Tutoriel C#.Net >Code d'implémentation sur la façon d'utiliser ref et Span
Cet article présente principalement le code d'implémentation simple de l'utilisation de ref et Span8742468051c85b06f0a0af9e3e506b5c dans .Net Core pour améliorer les performances du programme. Les amis dans le besoin peuvent s'y référer
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)++; }Les deux ci-dessus
. 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 = 32Voici les fonctionnalités fournies par C# 7.0 :
1.ref locals (référençant les variables locales)
int i = 42; ref var x = ref i; x = x + 1; // i = 43Dans cet exemple C'est une référence x à la variable locale i. Lorsque la valeur de x est modifiée, la valeur de la variable i change également.
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];obtient la référence à l'élément du tableau via l'indice, et lorsque en changeant la valeur de référence, le tableau changera également en conséquence.
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>Ci-dessus, nous avons vu les opérations de type pointeur (T*) fournies par le mot-clé ref sur une seule valeur
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 {...} } ... }Ensuite, j'utiliserai un exemple intuitif pour illustrer le scénario d'utilisation. de Span ; Prenons comme exemple l'interception de caractères et la conversion de caractères (conversion en entier) : S'il y a une
chaînechaîne
<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!