ホームページ >バックエンド開発 >C#.Net チュートリアル >コード分析: ref と Span
この記事では、.Net Core で ref と Span8742468051c85b06f0a0af9e3e506b5c を使用してプログラムのパフォーマンスを向上させる簡単な実装コードを主に紹介します。必要な方は参考にしてください。 ref については、多くの学生がすでに知っています。ref は、開発者にローカル変数参照と値参照を返すメカニズムを提供する C# 7.0 の言語機能です。
Span も ref 構文に基づく複雑なデータ型です。記事の後半では、その使用方法を示す例を示します。2. Ref キーワード
ref キーにしろ out キーにしろ、C 言語でのポインタの操作と同様に、このような高度な構文は常に何らかの副作用を伴いますが、理解と操作が難しい言語機能です。私はこれが大したことではないと思いますし、すべての C# 開発者がこれらの内部動作メカニズムを深く理解する必要があるわけではありません。複雑さは関係なく、人々に自由な選択肢を提供するだけであり、リスクと柔軟性は決して両立しないと思います。 。
参照とポインターの類似性を説明するために、いくつかの例を見てみましょう。 もちろん、次の使用方法は C# 7.0 より前でも使用できます。
public static void IncrementByRef(ref int x) { x++; } public unsafe static void IncrementByPointer(int* x) { (*x)++; }
上記の 2 つの関数は、それぞれ ref と unsafe ポインターを使用します。パラメータ +1 を完成させます。
int i = 30; IncrementByRef(ref i); // i = 31 unsafe{ IncrementByPointer(&i); } // i = 32
1.ref ローカル (ローカル変数の参照)
int i = 42; ref var x = ref i; x = x + 1; // i = 43
この例では、ローカル i の参照 x です。変数、x を変更すると、i 変数の値も変更されます。
2.ref returns (戻り値参照)
ref returns は、C# 7 の強力な機能です。次のコードは、その機能を最もよく反映しています:
public static ref int GetArrayRef(int[] items, int index) => ref items[index];
添字を介して配列内の項目の参照を取得します。参照値が変更されると、それに応じて配列も変更されます。
System.Span は、System.Memory.dll アセンブリの下にある .Net Core コアの一部です。現在、この機能は独立していますが、将来 CoreFx に統合される可能性があります
使用方法?次の NuGet パッケージは、.Net Core 2.0 SDK によって作成されたプロジェクトの下で参照されます:
<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>上記では、ref キーワードを使用して提供できる単一値オブジェクトを操作するポインター (T*) のような方法を見てきました。 。基本的に、.NET システムではポインターの操作は良いこととは考えられていません。もちろん、.NET は単一値の参照を安全に操作するための ref を提供します。しかし、単一の値は、「ポインター」を使用するユーザーのニーズのほんの一部にすぎません。ポインターの場合、より一般的な状況は、連続したメモリ空間で一連の「要素」を操作する場合です。 スパンは、既知の長さとタイプの連続したメモリ ブロックとして表されます。メモリ領域ポインタへの安全なアクセスを提供するという点で、多くの点で T[] または ArraySegment と非常に似ています。実際、これが .NET の操作 (void*) ポインターの抽象化になることは、C/C++ に詳しい開発者であればよく理解できるはずです。
スパン機能は次のとおりです:
•配列、アンマネージ ポインタ、スタック ポインタ、固定または固定された管理データ、および値の内部領域への参照を含む、すべての連続メモリ空間の型システムを抽象化します
• CLR 標準のオブジェクト型と値型をサポートします•ジェネリクスをサポートします •独自に管理および解放する必要があるポインターとは異なり、GC をサポートします 構文的にも意味的にも ref: に関連する Span の定義を見てみましょう。
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 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");文字列を int に変換するアルゴリズムは、Span の典型的な使用シナリオでもあります。公式のシナリオも同様です。連続メモリの再利用シナリオ。 conversonコンバージョンコードは次のとおりです:
string content = "content-length:123",
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");e44。最後に
以上がコード分析: ref と Span