{"id":427572,"date":"2024-07-27T15:00:43","date_gmt":"2024-07-27T15:00:43","guid":{"rendered":"http:\/\/savepearlharbor.com\/?p=427572"},"modified":"-0001-11-30T00:00:00","modified_gmt":"-0001-11-29T21:00:00","slug":"","status":"publish","type":"post","link":"https:\/\/savepearlharbor.com\/?p=427572","title":{"rendered":"<span>Spans in C#: Your Best Friend for Efficient Coding<\/span>"},"content":{"rendered":"<div><!--[--><!--]--><\/div>\n<div id=\"post-content-body\">\n<div>\n<div class=\"article-formatted-body article-formatted-body article-formatted-body_version-2\">\n<div xmlns=\"http:\/\/www.w3.org\/1999\/xhtml\">\n<figure class=\"\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w780q1\/getpro\/habr\/upload_files\/dd3\/b32\/dbb\/dd3b32dbb2ae3c3c00664f883bc21e99.jpg\" alt=\"As Midjourney see Mister Span\" title=\"As Midjourney see Mister Span\" width=\"512\" height=\"512\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/dd3\/b32\/dbb\/dd3b32dbb2ae3c3c00664f883bc21e99.jpg\" data-blurred=\"true\"\/><\/p>\n<div><figcaption>As Midjourney see Mister Span<\/figcaption><\/div>\n<\/figure>\n<p>I\u2019ve been wanting to sort it out about String memory optimization and all these ways to improve the performance and memory usage for Collections and Arrays in C#(as you remember String is an array of chars, loaded a bit differently but anyway) code. I finally managed to find some time to dive deeper into the System.Span.<\/p>\n<p>I have put together this guide to share what I\u2019ve learned. It\u2019s filled with practical tips and examples to help you leverage Spans in your own projects. If you want to optimize your C# code, this guide is a great place to start!<\/p>\n<p>So, you want to make your C# code run faster and use memory more efficiently? Meet Spans: the handy tool that simplifies handling blocks of memory and helps your applications perform better. Let\u2019s dive into how Spans work, explore practical examples, understand their differences, and see how they can be used for JSON parsing, along with converting collections to and from Spans.<\/p>\n<h3>What Are\u00a0Spans?<\/h3>\n<p>In C#, <code>Span&lt;T&gt;<\/code> and <code>ReadOnlySpan&lt;T&gt;<\/code> are structures that represent contiguous regions of memory. They allow you to work with slices of data without the overhead of additional memory allocations.<\/p>\n<ul>\n<li>\n<p><code>Span&lt;T&gt;<\/code>: Allows both reading and writing operations on memory.<\/p>\n<\/li>\n<li>\n<p><code>ReadOnlySpan&lt;T&gt;<\/code>: Used for read-only operations, ensuring the data cannot be modified.<\/p>\n<\/li>\n<\/ul>\n<p>Spans are particularly useful for performance-critical scenarios, as they enable direct access to data and efficient memory usage.<\/p>\n<h3>Why Should You Care About\u00a0Spans?<\/h3>\n<ol>\n<li>\n<p><strong>Faster Performance<\/strong>: Spans help reduce memory allocations and garbage collection pressure. They allow you to work with data directly and efficiently.<\/p>\n<\/li>\n<li>\n<p><strong>Safer Code<\/strong>: Spans prevent common errors like buffer overruns and provide bounds-checking.<\/p>\n<\/li>\n<li>\n<p><strong>Versatility<\/strong>: They work with arrays, strings, and slices of other memory regions, making them adaptable for various data-handling scenarios.<\/p>\n<\/li>\n<\/ol>\n<h3>How Spans Are Implemented<\/h3>\n<p>Under the hood, Spans are designed to be lightweight and fast:<\/p>\n<ul>\n<li>\n<p><strong>Stack Allocation<\/strong>: Spans are typically allocated on the stack, which is faster and avoids heap allocation.<\/p>\n<\/li>\n<li>\n<p><strong>Memory Safety<\/strong>: They ensure safe access to memory, with built-in bounds checking to prevent out-of-bounds errors.<\/p>\n<\/li>\n<li>\n<p><strong>No Heap Overhead<\/strong>: Unlike arrays, Spans don\u2019t create additional heap allocations, reducing memory overhead and improving performance.<\/p>\n<\/li>\n<\/ul>\n<h3>Differences Between Span and ReadOnlySpan<\/h3>\n<p>While both <code>Span&lt;T&gt;<\/code> and <code>ReadOnlySpan&lt;T&gt;<\/code> handle contiguous memory, they differ in their usage and capabilities:<\/p>\n<p><code>Span&lt;T&gt;<\/code>:<\/p>\n<ul>\n<li>\n<p><strong>Mutable<\/strong>: You can modify the contents of a <code>Span&lt;T&gt;<\/code>.<\/p>\n<\/li>\n<li>\n<p><strong>Example<\/strong>: Changing elements in an array or buffer.<\/p>\n<\/li>\n<\/ul>\n<pre><code class=\"cs\">int[] numbers = { 1, 2, 3, 4, 5 }; Span&lt;int&gt; span = new Span&lt;int&gt;(numbers); span[0] = 10; \/\/ Modifies the original array Console.WriteLine(numbers[0]); \/\/ Outputs 10<\/code><\/pre>\n<p><code>ReadOnlySpan&lt;T&gt;<\/code>:<\/p>\n<ul>\n<li>\n<p><strong>Immutable<\/strong>: You cannot modify the contents of a <code>ReadOnlySpan&lt;T&gt;<\/code>.<\/p>\n<\/li>\n<li>\n<p><strong>Example<\/strong>: Reading values from a string or array without altering them.<\/p>\n<\/li>\n<\/ul>\n<pre><code class=\"cs\">string text = \"Hello, World!\"; ReadOnlySpan&lt;char&gt; readOnlySpan = text.AsSpan(); \/\/ readOnlySpan[0] = 'h'; \/\/ This line would cause a compilation error Console.WriteLine(readOnlySpan.ToString()); \/\/ Outputs \"Hello, World!\"<\/code><\/pre>\n<h3>Collection to Span Conversions<\/h3>\n<p>Spans are designed to work seamlessly with collections like arrays, making it easy to convert between collections and spans.<\/p>\n<p><strong>From Array to Span:<\/strong><\/p>\n<pre><code class=\"cs\">int[] numbers = { 1, 2, 3, 4, 5 }; Span&lt;int&gt; spanFromArray = new Span&lt;int&gt;(numbers);<\/code><\/pre>\n<p><strong>From Span to Array:<\/strong><\/p>\n<pre><code class=\"cs\">Span&lt;int&gt; span = stackalloc int[] { 1, 2, 3, 4, 5 }; int[] arrayFromSpan = span.ToArray();<\/code><\/pre>\n<p><strong>From String to ReadOnlySpan:<\/strong><\/p>\n<pre><code class=\"cs\">string text = \"Hello, World!\"; ReadOnlySpan&lt;char&gt; spanFromString = text.AsSpan();<\/code><\/pre>\n<p>From ReadOnlySpan to String:<\/p>\n<pre><code class=\"cs\">ReadOnlySpan&lt;char&gt; span = \"Hello, World!\".AsSpan(); string strFromSpan = span.ToString(); \/\/ Note: Converts to a new string<\/code><\/pre>\n<h3>Practical Examples of Collection Conversion<\/h3>\n<p>Example: Working with Arrays and Spans<\/p>\n<pre><code class=\"cs\">int[] array = { 1, 2, 3, 4, 5 }; Span&lt;int&gt; span = array; span[0] = 10; \/\/ Modifies the original array Console.WriteLine(string.Join(\", \", array)); \/\/ Outputs: 10, 2, 3, 4, 5<\/code><\/pre>\n<p>Example: Converting a Span to an Array<\/p>\n<pre><code class=\"cs\">Span&lt;int&gt; span = stackalloc int[] { 10, 20, 30 }; int[] array = span.ToArray(); Console.WriteLine(string.Join(\", \", array)); \/\/ Outputs: 10, 20, 30<\/code><\/pre>\n<p>Example: Extracting a Substring Using ReadOnlySpan<\/p>\n<pre><code class=\"cs\">string text = \"Hello, World!\"; ReadOnlySpan&lt;char&gt; span = text.AsSpan(); ReadOnlySpan&lt;char&gt; helloSpan = span.Slice(0, 5); Console.WriteLine(helloSpan.ToString()); \/\/ Outputs: HelloHello<\/code><\/pre>\n<h3>Practical example: Writing own JSON Parser with\u00a0Spans<\/h3>\n<p>Spans are especially useful for handling string data efficiently. So now lets try to write our own JSON parser which will work without creating unnecessary intermediate strings.<\/p>\n<p><strong>Simple JSON Parser<\/strong><\/p>\n<pre><code class=\"cs\">public void ParseJson(ReadOnlySpan&lt;char&gt; jsonData) {     \/\/ Find the start of the value for a specific key     ReadOnlySpan&lt;char&gt; key = \"name\";     int keyStart = jsonData.IndexOf(key);          if (keyStart == -1)     {         Console.WriteLine(\"Key not found\");         return;     }          \/\/ Move past the key and find the colon     int valueStart = jsonData.Slice(keyStart + key.Length).IndexOf(':') + keyStart + key.Length + 1;     int valueEnd = jsonData.Slice(valueStart).IndexOf(',');          if (valueEnd == -1) \/\/ If no comma, this is the last value     {         valueEnd = jsonData.Slice(valueStart).IndexOf('}');     }          \/\/ Extract and print the value     ReadOnlySpan&lt;char&gt; value = jsonData.Slice(valueStart, valueEnd);     Console.WriteLine(value.ToString().Trim('\"')); \/\/ Remove quotes }<\/code><\/pre>\n<p>The parser is great with atomic data types but doesn&#8217;t support complex types like Arrays or inner Objects.<\/p>\n<p><strong>So let&#8217;s add a <em>Span-<\/em>based <em>Array<\/em> parser:<\/strong><\/p>\n<pre><code class=\"cs\">public void ProcessJsonArray(ReadOnlySpan&lt;char&gt; jsonArray) {     int currentIndex = 0;          while (currentIndex &lt; jsonArray.Length)     {         int start = jsonArray.Slice(currentIndex).IndexOf('{');         if (start == -1) break; \/\/ No more objects          int end = jsonArray.Slice(currentIndex).IndexOf('}');         if (end == -1) break; \/\/ Incomplete object                  ReadOnlySpan&lt;char&gt; jsonObject = jsonArray.Slice(currentIndex + start, end - start + 1);         ProcessJsonObject(jsonObject);                  currentIndex += end + 1; \/\/ Move past the current object     } }<\/code><\/pre>\n<p>And add nested objects support:<\/p>\n<pre><code class=\"cs\">private void ProcessJsonObject(ReadOnlySpan&lt;char&gt; jsonObject) {     \/\/ Simple key-value extraction, assuming keys and values are properly formatted     int colonIndex = jsonObject.IndexOf(':');     ReadOnlySpan&lt;char&gt; key = jsonObject.Slice(1, colonIndex - 2); \/\/ Skipping surrounding quotes     ReadOnlySpan&lt;char&gt; value = jsonObject.Slice(colonIndex + 1).Trim(); \/\/ Extract value and trim          Console.WriteLine($\"Key: {key.ToString()}, Value: {value.ToString()}\"); }<\/code><\/pre>\n<p><strong>Putting It All Together: Parsing JSON Data<\/strong><\/p>\n<p>Here\u2019s how you might use all the above functions together to parse a complete JSON string:<\/p>\n<pre><code class=\"cs\">public void ParseJson(ReadOnlySpan&lt;char&gt; jsonData) {     int start = 0;     while (start &lt; jsonData.Length)     {         int objectStart = jsonData.Slice(start).IndexOf('{');         if (objectStart == -1) break;          int objectEnd = jsonData.Slice(start).IndexOf('}');         if (objectEnd == -1) break;          ReadOnlySpan&lt;char&gt; jsonObject = jsonData.Slice(start + objectStart, objectEnd - objectStart + 1);         ProcessJsonObject(jsonObject);          start += objectEnd + 1;     } }<\/code><\/pre>\n<p>Well done! Now we have our own memory-effective JSON Parser implementation and can finally forget about these Newtonsoft.Json nuget package update problems\u2026probably didn\u2019t face it latest 3\u20134 years, because Microsoft wrote its own implementation, but if you face\u200a\u2014\u200anow you know what to do!<\/p>\n<h3>Things to Watch Out\u00a0For<\/h3>\n<ul>\n<li>\n<p><strong>Scope<\/strong>: Spans are stack-allocated and should be used within the method where they\u2019re created.<\/p>\n<\/li>\n<li>\n<p><strong>Pinning<\/strong>: When dealing with unmanaged memory, be cautious about pinning as it can affect garbage collection.<\/p>\n<\/li>\n<li>\n<p><strong>Compatibility<\/strong>: Ensure that your development environment supports Spans, especially with older frameworks.<\/p>\n<\/li>\n<\/ul>\n<h3>Wrap-Up<\/h3>\n<p>Spans are a powerful feature in C# that can help you manage memory efficiently and safely. By understanding the differences between <code>Span&lt;T&gt;<\/code> and <code>ReadOnlySpan&lt;T&gt;<\/code>, and how to convert between collections and spans, you can write more efficient and cleaner code. Use Spans for task<\/p>\n<\/p>\n<\/div>\n<\/div>\n<\/div>\n<p><!----><!----><\/div>\n<p><!----><!----><br \/> \u0441\u0441\u044b\u043b\u043a\u0430 \u043d\u0430 \u043e\u0440\u0438\u0433\u0438\u043d\u0430\u043b \u0441\u0442\u0430\u0442\u044c\u0438 <a href=\"https:\/\/habr.com\/ru\/articles\/831844\/\"> https:\/\/habr.com\/ru\/articles\/831844\/<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<div><!--[--><!--]--><\/div>\n<div id=\"post-content-body\">\n<div>\n<div class=\"article-formatted-body article-formatted-body article-formatted-body_version-2\">\n<div xmlns=\"http:\/\/www.w3.org\/1999\/xhtml\">\n<figure class=\"\">\n<div><figcaption>As Midjourney see Mister Span<\/figcaption><\/div>\n<\/figure>\n<p>I\u2019ve been wanting to sort it out about String memory optimization and all these ways to improve the performance and memory usage for Collections and Arrays in C#(as you remember String is an array of chars, loaded a bit differently but anyway) code. I finally managed to find some time to dive deeper into the System.Span.<\/p>\n<p>I have put together this guide to share what I\u2019ve learned. It\u2019s filled with practical tips and examples to help you leverage Spans in your own projects. If you want to optimize your C# code, this guide is a great place to start!<\/p>\n<p>So, you want to make your C# code run faster and use memory more efficiently? Meet Spans: the handy tool that simplifies handling blocks of memory and helps your applications perform better. Let\u2019s dive into how Spans work, explore practical examples, understand their differences, and see how they can be used for JSON parsing, along with converting collections to and from Spans.<\/p>\n<h3>What Are\u00a0Spans?<\/h3>\n<p>In C#, <code>Span&lt;T&gt;<\/code> and <code>ReadOnlySpan&lt;T&gt;<\/code> are structures that represent contiguous regions of memory. They allow you to work with slices of data without the overhead of additional memory allocations.<\/p>\n<ul>\n<li>\n<p><code>Span&lt;T&gt;<\/code>: Allows both reading and writing operations on memory.<\/p>\n<\/li>\n<li>\n<p><code>ReadOnlySpan&lt;T&gt;<\/code>: Used for read-only operations, ensuring the data cannot be modified.<\/p>\n<\/li>\n<\/ul>\n<p>Spans are particularly useful for performance-critical scenarios, as they enable direct access to data and efficient memory usage.<\/p>\n<h3>Why Should You Care About\u00a0Spans?<\/h3>\n<ol>\n<li>\n<p><strong>Faster Performance<\/strong>: Spans help reduce memory allocations and garbage collection pressure. They allow you to work with data directly and efficiently.<\/p>\n<\/li>\n<li>\n<p><strong>Safer Code<\/strong>: Spans prevent common errors like buffer overruns and provide bounds-checking.<\/p>\n<\/li>\n<li>\n<p><strong>Versatility<\/strong>: They work with arrays, strings, and slices of other memory regions, making them adaptable for various data-handling scenarios.<\/p>\n<\/li>\n<\/ol>\n<h3>How Spans Are Implemented<\/h3>\n<p>Under the hood, Spans are designed to be lightweight and fast:<\/p>\n<ul>\n<li>\n<p><strong>Stack Allocation<\/strong>: Spans are typically allocated on the stack, which is faster and avoids heap allocation.<\/p>\n<\/li>\n<li>\n<p><strong>Memory Safety<\/strong>: They ensure safe access to memory, with built-in bounds checking to prevent out-of-bounds errors.<\/p>\n<\/li>\n<li>\n<p><strong>No Heap Overhead<\/strong>: Unlike arrays, Spans don\u2019t create additional heap allocations, reducing memory overhead and improving performance.<\/p>\n<\/li>\n<\/ul>\n<h3>Differences Between Span and ReadOnlySpan<\/h3>\n<p>While both <code>Span&lt;T&gt;<\/code> and <code>ReadOnlySpan&lt;T&gt;<\/code> handle contiguous memory, they differ in their usage and capabilities:<\/p>\n<p><code>Span&lt;T&gt;<\/code>:<\/p>\n<ul>\n<li>\n<p><strong>Mutable<\/strong>: You can modify the contents of a <code>Span&lt;T&gt;<\/code>.<\/p>\n<\/li>\n<li>\n<p><strong>Example<\/strong>: Changing elements in an array or buffer.<\/p>\n<\/li>\n<\/ul>\n<pre><code class=\"cs\">int[] numbers = { 1, 2, 3, 4, 5 }; Span&lt;int&gt; span = new Span&lt;int&gt;(numbers); span[0] = 10; \/\/ Modifies the original array Console.WriteLine(numbers[0]); \/\/ Outputs 10<\/code><\/pre>\n<p><code>ReadOnlySpan&lt;T&gt;<\/code>:<\/p>\n<ul>\n<li>\n<p><strong>Immutable<\/strong>: You cannot modify the contents of a <code>ReadOnlySpan&lt;T&gt;<\/code>.<\/p>\n<\/li>\n<li>\n<p><strong>Example<\/strong>: Reading values from a string or array without altering them.<\/p>\n<\/li>\n<\/ul>\n<pre><code class=\"cs\">string text = \"Hello, World!\"; ReadOnlySpan&lt;char&gt; readOnlySpan = text.AsSpan(); \/\/ readOnlySpan[0] = 'h'; \/\/ This line would cause a compilation error Console.WriteLine(readOnlySpan.ToString()); \/\/ Outputs \"Hello, World!\"<\/code><\/pre>\n<h3>Collection to Span Conversions<\/h3>\n<p>Spans are designed to work seamlessly with collections like arrays, making it easy to convert between collections and spans.<\/p>\n<p><strong>From Array to Span:<\/strong><\/p>\n<pre><code class=\"cs\">int[] numbers = { 1, 2, 3, 4, 5 }; Span&lt;int&gt; spanFromArray = new Span&lt;int&gt;(numbers);<\/code><\/pre>\n<p><strong>From Span to Array:<\/strong><\/p>\n<pre><code class=\"cs\">Span&lt;int&gt; span = stackalloc int[] { 1, 2, 3, 4, 5 }; int[] arrayFromSpan = span.ToArray();<\/code><\/pre>\n<p><strong>From String to ReadOnlySpan:<\/strong><\/p>\n<pre><code class=\"cs\">string text = \"Hello, World!\"; ReadOnlySpan&lt;char&gt; spanFromString = text.AsSpan();<\/code><\/pre>\n<p>From ReadOnlySpan to String:<\/p>\n<pre><code class=\"cs\">ReadOnlySpan&lt;char&gt; span = \"Hello, World!\".AsSpan(); string strFromSpan = span.ToString(); \/\/ Note: Converts to a new string<\/code><\/pre>\n<h3>Practical Examples of Collection Conversion<\/h3>\n<p>Example: Working with Arrays and Spans<\/p>\n<pre><code class=\"cs\">int[] array = { 1, 2, 3, 4, 5 }; Span&lt;int&gt; span = array; span[0] = 10; \/\/ Modifies the original array Console.WriteLine(string.Join(\", \", array)); \/\/ Outputs: 10, 2, 3, 4, 5<\/code><\/pre>\n<p>Example: Converting a Span to an Array<\/p>\n<pre><code class=\"cs\">Span&lt;int&gt; span = stackalloc int[] { 10, 20, 30 }; int[] array = span.ToArray(); Console.WriteLine(string.Join(\", \", array)); \/\/ Outputs: 10, 20, 30<\/code><\/pre>\n<p>Example: Extracting a Substring Using ReadOnlySpan<\/p>\n<pre><code class=\"cs\">string text = \"Hello, World!\"; ReadOnlySpan&lt;char&gt; span = text.AsSpan(); ReadOnlySpan&lt;char&gt; helloSpan = span.Slice(0, 5); Console.WriteLine(helloSpan.ToString()); \/\/ Outputs: HelloHello<\/code><\/pre>\n<h3>Practical example: Writing own JSON Parser with\u00a0Spans<\/h3>\n<p>Spans are especially useful for handling string data efficiently. So now lets try to write our own JSON parser which will work without creating unnecessary intermediate strings.<\/p>\n<p><strong>Simple JSON Parser<\/strong><\/p>\n<pre><code class=\"cs\">public void ParseJson(ReadOnlySpan&lt;char&gt; jsonData) {     \/\/ Find the start of the value for a specific key     ReadOnlySpan&lt;char&gt; key = \"name\";     int keyStart = jsonData.IndexOf(key);          if (keyStart == -1)     {         Console.WriteLine(\"Key not found\");         return;     }          \/\/ Move past the key and find the colon     int valueStart = jsonData.Slice(keyStart + key.Length).IndexOf(':') + keyStart + key.Length + 1;     int valueEnd = jsonData.Slice(valueStart).IndexOf(',');          if (valueEnd == -1) \/\/ If no comma, this is the last value     {         valueEnd = jsonData.Slice(valueStart).IndexOf('}');     }          \/\/ Extract and print the value     ReadOnlySpan&lt;char&gt; value = jsonData.Slice(valueStart, valueEnd);     Console.WriteLine(value.ToString().Trim('\"')); \/\/ Remove quotes }<\/code><\/pre>\n<p>The parser is great with atomic data types but doesn&#8217;t support complex types like Arrays or inner Objects.<\/p>\n<p><strong>So let&#8217;s add a <em>Span-<\/em>based <em>Array<\/em> parser:<\/strong><\/p>\n<pre><code class=\"cs\">public void ProcessJsonArray(ReadOnlySpan&lt;char&gt; jsonArray) {     int currentIndex = 0;          while (currentIndex &lt; jsonArray.Length)     {         int start = jsonArray.Slice(currentIndex).IndexOf('{');         if (start == -1) break; \/\/ No more objects          int end = jsonArray.Slice(currentIndex).IndexOf('}');         if (end == -1) break; \/\/ Incomplete object                  ReadOnlySpan&lt;char&gt; jsonObject = jsonArray.Slice(currentIndex + start, end - start + 1);         ProcessJsonObject(jsonObject);                  currentIndex += end + 1; \/\/ Move past the current object     } }<\/code><\/pre>\n<p>And add nested objects support:<\/p>\n<pre><code class=\"cs\">private void ProcessJsonObject(ReadOnlySpan&lt;char&gt; jsonObject) {     \/\/ Simple key-value extraction, assuming keys and values are properly formatted     int colonIndex = jsonObject.IndexOf(':');     ReadOnlySpan&lt;char&gt; key = jsonObject.Slice(1, colonIndex - 2); \/\/ Skipping surrounding quotes     ReadOnlySpan&lt;char&gt; value = jsonObject.Slice(colonIndex + 1).Trim(); \/\/ Extract value and trim          Console.WriteLine($\"Key: {key.ToString()}, Value: {value.ToString()}\"); }<\/code><\/pre>\n<p><strong>Putting It All Together: Parsing JSON Data<\/strong><\/p>\n<p>Here\u2019s how you might use all the above functions together to parse a complete JSON string:<\/p>\n<pre><code class=\"cs\">public void ParseJson(ReadOnlySpan&lt;char&gt; jsonData) {     int start = 0;     while (start &lt; jsonData.Length)     {         int objectStart = jsonData.Slice(start).IndexOf('{');         if (objectStart == -1) break;          int objectEnd = jsonData.Slice(start).IndexOf('}');         if (objectEnd == -1) break;          ReadOnlySpan&lt;char&gt; jsonObject = jsonData.Slice(start + objectStart, objectEnd - objectStart + 1);         ProcessJsonObject(jsonObject);          start += objectEnd + 1;     } }<\/code><\/pre>\n<p>Well done! Now we have our own memory-effective JSON Parser implementation and can finally forget about these Newtonsoft.Json nuget package update problems\u2026probably didn\u2019t face it latest 3\u20134 years, because Microsoft wrote its own implementation, but if you face\u200a\u2014\u200anow you know what to do!<\/p>\n<h3>Things to Watch Out\u00a0For<\/h3>\n<ul>\n<li>\n<p><strong>Scope<\/strong>: Spans are stack-allocated and should be used within the method where they\u2019re created.<\/p>\n<\/li>\n<li>\n<p><strong>Pinning<\/strong>: When dealing with unmanaged memory, be cautious about pinning as it can affect garbage collection.<\/p>\n<\/li>\n<li>\n<p><strong>Compatibility<\/strong>: Ensure that your development environment supports Spans, especially with older frameworks.<\/p>\n<\/li>\n<\/ul>\n<h3>Wrap-Up<\/h3>\n<p>Spans are a powerful feature in C# that can help you manage memory efficiently and safely. By understanding the differences between <code>Span&lt;T&gt;<\/code> and <code>ReadOnlySpan&lt;T&gt;<\/code>, and how to convert between collections and spans, you can write more efficient and cleaner code. Use Spans for task<\/p>\n<\/p>\n<\/div>\n<\/div>\n<\/div>\n<p><!----><!----><\/div>\n<p><!----><!----><br \/> \u0441\u0441\u044b\u043b\u043a\u0430 \u043d\u0430 \u043e\u0440\u0438\u0433\u0438\u043d\u0430\u043b \u0441\u0442\u0430\u0442\u044c\u0438 <a href=\"https:\/\/habr.com\/ru\/articles\/831844\/\"> https:\/\/habr.com\/ru\/articles\/831844\/<\/a><br \/><\/br><\/br><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[],"tags":[],"class_list":["post-427572","post","type-post","status-publish","format-standard","hentry"],"_links":{"self":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/427572","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=427572"}],"version-history":[{"count":0,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/427572\/revisions"}],"wp:attachment":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=427572"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=427572"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=427572"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}