In diesem Artikel wird hauptsächlich der einfache Implementierungscode für die Verwendung von ref und Span
1. Vorwort
Tatsächlich wissen viele Studenten bereits, dass es sich bei Ref um eine Sprachfunktion von C# 7.0 handelt. Das wird für die Personalentwicklung verwendet und stellt Mechanismen für die Rückgabe lokaler variabler Referenzen und Wertreferenzen bereit.
Span ist ebenfalls ein komplexer Datentyp, der auf der Ref-Syntax basiert. In der zweiten Hälfte des Artikels werde ich ein Beispiel zeigen, das zeigt, wie man ihn verwendet.
2. Ref-Schlüsselwort
Ob Ref- oder Out-Taste, es handelt sich um eine Sprachfunktion, die schwer zu verstehen und zu bedienen ist, z da C-Sprache dasselbe ist wie Betriebszeiger, bringt eine solche High-Level-Syntax immer einige Nebenwirkungen mit sich, aber ich glaube nicht, dass das irgendetwas ist, und nicht jeder C#-Entwickler muss ein tiefes Verständnis davon haben Ich denke, dass, egal wie komplex die Dinge sind, es den Menschen nur eine freie Wahl bietet. Risiko und Flexibilität sind immer unvereinbar.
Sehen wir uns einige Beispiele an, um die Ähnlichkeit zwischen Referenzen und Zeigern zu veranschaulichen. Natürlich können die folgenden Verwendungsmethoden vor C# 7.0 verwendet werden:
public static void IncrementByRef(ref int x) { x++; } public unsafe static void IncrementByPointer(int* x) { (*x)++; }
Die beiden oben genannten Die Funktion verwendet Ref- und nicht-sichere -Zeiger, um Parameter +1 zu vervollständigen.
int i = 30; IncrementByRef(ref i); // i = 31 unsafe{ IncrementByPointer(&i); } // i = 32
1.ref locals (verweisen auf lokale Variablen)
int i = 42; ref var x = ref i; x = x + 1; // i = 43
2.ref returns (Rückgabewertreferenz)
ref returns ist eine leistungsstarke Funktion in C# 7. Der folgende Code ist die wichtigste effektiv Diese Funktion spiegelt ihre Eigenschaften wider und stellt einen Verweis auf ein Element im Arraybereit, das von int zurückgegeben wird:
public static ref int GetArrayRef(int[] items, int index) => ref items[index];
3. Span
System.Span ist Teil des .Net Core-Kerns in System.Memory.Wie verwende ich sie? Auf das folgende NuGet-Paket wird unter dem vom .Net Core 2.0 SDK erstellten Projekt verwiesen:<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>
Objekt Weg. Grundsätzlich gilt das Betreiben von Zeigern unter dem .NET-System nicht als gutes Ereignis. Natürlich stellt uns .NET Referenzen für den sicheren Betrieb von Einzelwertreferenzen zur Verfügung. Ein einzelner Wert stellt jedoch nur einen kleinen Teil der Anforderungen des Benutzers für die Verwendung von „Zeigern“ dar. Die häufigere Situation liegt vor, wenn eine Reihe von „Elementen“ in einem kontinuierlichen Speicherbereich betrieben werden.
Span wird als zusammenhängender Speicherblock bekannter Länge und bekannter Art dargestellt. In vielerlei Hinsicht ist es T[] oder ArraySegment sehr ähnlich, da es sicheren Zugriff auf Speicherbereichszeiger bietet. Tatsächlich verstehe ich, dass es sich um eine Abstraktion des Operationszeigers (void*) in .NET handelt. Entwickler, die mit C/C++ vertraut sind, sollten besser wissen, was das bedeutet.Die Eigenschaften von Span sind wie folgt:
• Abstrahiert das Typsystem aller kontinuierlichen Speicherbereiche, einschließlich: Arrays, nicht verwaltete Zeiger, Stapelzeiger, feste oder angeheftete verwaltete Daten und Verweise auf interne Wertebereiche•Unterstützt CLR-Standardobjekttypen und -werttypen
•Unterstützt Generika
•Unterstützt GC, im Gegensatz zu Zeigern, die verwaltet werden müssen
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 {...} } ... }
String</a>String<code><a href="//m.sbmmt.com/wiki/57.html" target="_blank">string</a> content = "content-length:123",
gibt, content = "content -length: 123",Um 123 in eine Ganzzahl umzuwandeln, besteht der übliche Ansatz darin, zuerst Substrzu verwenden, um die Zeichenfolge abzuschneiden, die nichts mit numerischen Zeichen zu tun hat. Der Konvertierungscode lautet wie folgt :
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");
Warum dieses Beispiel verwenden? Bei jeder Operation wird ein neues String-Objekt generiert Wird beim Ausführen von int.Parse wiederholt ausgeführt. Wenn eine große Anzahl von Vorgängen ausgeführt wird, wird der GC unter Druck gesetzt.
Verwenden Sie Span, um diesen Algorithmus zu implementieren:
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的性能日后会越来越强大。
Das obige ist der detaillierte Inhalt vonImplementierungscode zur Verwendung von ref und Span