毛姥姥是只猫 發表於 2020-10-13 12:59:00

C# 中 System.Range 结构体

<blockquote>
<p>翻译自 John Demetriou 2020年4月6日 的文章 《C# 8 Is Introducing Ranges》,补充了一些内容</p>
</blockquote>
<p>我们之前讨论过的 C# 中的一个特性 <strong>System.Index 结构体</strong><sup class="footnote-ref"></sup>,与另一特性 <strong>System.Range 结构体</strong> 是携手并进的。</p>
<p>在 C# 8.0 之前,没有访问集合中任意部分的范围或切片的语法。开发人员通常不得不执行一些自定义的切片操作,或者依靠诸如 <code>array.Skip(5).Take(2);</code> 的 LINQ 方法。</p>
<p>现在 C# 添加了一个新的小特性,它可以帮助人们从一个大的数组项目中获取一个小范围的项目。</p>
<p>让我们来考虑一下。假设我们有一个项目数组,我们仅需展示其中的一部分。通常情况下,我们只需要循环这部分,然后像下面这样输出它们。</p>
<pre><code class="language-csharp">var array = new string[]
    {
      "Item0",
      "Item1",
      "Item2",
      "Item3",
      "Item4",
      "Item5",
      "Item6",
      "Item7",
      "Item8",
      "Item9"
    };

for (int i = 1; i &lt;= 5; i++)
{
    Console.WriteLine(array);
}
</code></pre>
<p>因此当我们仅需要几个特定的项,我们通过控制索引值来获取它们。</p>
<p>通过使用范围(<code>Range</code>),我们可以用以下方式来替换:</p>
<pre><code class="language-csharp">var array = new string[]
    {
      "Item0",
      "Item1",
      "Item2",
      "Item3",
      "Item4",
      "Item5",
      "Item6",
      "Item7",
      "Item8",
      "Item9"
    };

foreach (var item in array)
{
    Console.WriteLine(item);
}
</code></pre>
<p>在这里,第一次使用的人会注意到一个奇怪的情况——它只会打印四项。为什么呢?这是因为<strong>范围(<code>Range</code>)包含开始,但不包含末尾</strong>。<br>
如果想要与上面的 <code>for</code> 循环有相同的结果,我们的 <code>foreach</code> 循环应该是:</p>
<pre><code class="language-csharp">foreach (var item in array)
{
    Console.WriteLine(item);
}
</code></pre>
<h2 id="range-的一些示例">Range 的一些示例</h2>
<p>1、从索引 1(包含) 到末尾(包含)</p>
<pre><code class="language-csharp">foreach (var item in array)
{
    Console.WriteLine(item);
}
</code></pre>
<p>2、从开始(包含)到索引 3(不包含)</p>
<pre><code class="language-csharp">foreach (var item in array[..3])
{
    Console.WriteLine(item);
}
</code></pre>
<p>3、结合以上两种,您可以得到一个语法上正确的以下版本</p>
<pre><code class="language-csharp">foreach (var item in array[..])
{
    Console.WriteLine(item);
}
</code></pre>
<p>它的意思是获取整个范围。</p>
<blockquote>
<p>译者注<br>
它也等同于下面两种写法:</p>
</blockquote>
<pre><code class="language-csharp">foreach (var item in array)
{
    Console.WriteLine(item);
}
</code></pre>
<pre><code class="language-csharp">foreach (var item in array)
{
    Console.WriteLine(item);
}
</code></pre>
<p>4、从索引 1(包含)到 <em>从末尾开始</em>的索引 1(不包含)</p>
<pre><code class="language-csharp">foreach (var item in array)
{
    Console.WriteLine(item);
}
</code></pre>
<p>在这里,它结合了[前面文章]<sup class="footnote-ref"></sup>中介绍的 <code>Index</code> 的 Hat 运算符(<code>^</code>)。</p>
<p>一个快速的解释,Hat 运算符(<code>^</code>),会给您一个特定的索引。如果您写 <code>^1</code>,也就是在请求最后一项的索引。如上所述,考虑到最后一个索引号是排除的,在一个有 10 项的序列中,请求索引项直到 <code>^1</code>,您也就是在请求索引项直到索引 9(索引从 0 开始),并且该项不包括在其中。<br>
我希望我讲清楚了。</p>
<h2 id="将范围作为变量">将范围作为变量</h2>
<p>我们前面所做的是,将范围(<code>Range</code>)作为类型传递。我们也可以将范围声明为一个变量:</p>
<pre><code class="language-csharp">Range range = 1..9;
</code></pre>
<p>然后,可以在 <code>[</code> 和 <code>]</code> 字符中使用该范围:</p>
<pre><code class="language-csharp">var subarray = array;
</code></pre>
<p>我们还可以将其作为方法的参数传递、将其存储为私有变量,或者用在任何业务逻辑所需的地方。</p>
<h2 id="范围的类型支持">范围的类型支持</h2>
<p>范围(<code>Range</code>)不能被用在 <code>List</code> 或者 <code>IEnumerable&lt;T&gt;</code>,但数组并不是唯一支持它的类型。</p>
<p>您还可以将索引(<code>Index</code>)和范围(<code>Range</code>) 与 <code>String</code>、<code>Span&lt;T&gt;</code><sup class="footnote-ref"></sup> 或 <code>ReadOnlySpan&lt;T&gt;</code><sup class="footnote-ref"></sup> 一起使用。</p>
<p>与字符串一起使用的例子基本上就是代替 <code>Substring</code> 方法,如下所示:</p>
<pre><code class="language-csharp">string s = "01234567";
string r = s; // r 将会是 "12"
</code></pre>
<p>对于每个担心 <code>List</code>(它可能是您通常用来替代数组的类型)不支持范围的人来说,<code>List</code> 从 .Net Framework 2.0 开始就已经有 <code>GetRange</code> 方法了。</p>
<br>
<hr>
<blockquote>
<p>以下为译者补充</p>
</blockquote>
<h2 id="索引和范围总结">索引和范围总结</h2>
<p>索引(<code>Index</code>)和范围(<code>Range</code>)为访问序列中的单个元素或范围提供了简洁的语法。</p>
<p>对索引和范围的语言支持依赖于<em>两个新类型</em>和<em>两个新运算符</em>:</p>
<ul>
<li><code>System.Index</code><sup class="footnote-ref"></sup> 类型表示一个序列索引。</li>
<li>Hat 运算符(<code>^</code>),指定一个索引与序列末尾相关,用于构造 <code>System.Index</code> 对象。</li>
<li><code>System.Range</code><sup class="footnote-ref"></sup> 类型表示序列的子范围。</li>
<li>范围运算符(<code>..</code>),用于指定范围的开始和末尾,就像操作数一样,用于构造 <code>System.Range</code> 对象。</li>
</ul>
<p>考虑数组 <code>sequence</code>, <code>0</code> 索引与 <code>sequence</code> 相同。 <code>^0</code> 索引与 <code>sequence</code> 相同。 请注意,<code>sequence[..^0]</code> 不会引发异常,就像 <code>sequence[..sequence.Length]</code> 一样。对于任意数字 <code>n</code>,索引 <code>^n</code> 与 <code>sequence.Length - n</code> 相同。 如下面代码中的注释所示:</p>
<pre><code class="language-csharp">var array = new string[]
{
               // index from start    index from end
    "Item0",   // 0                   ^9
    "Item1",   // 1                   ^8
    "Item2",   // 2                   ^7
    "Item3",   // 3                   ^6
    "Item4",   // 4                   ^5
    "Item5",   // 5                   ^4
    "Item6",   // 6                   ^3
    "Item7",   // 7                   ^2
    "Item8",   // 8                   ^1
};             // 9 (or array.Length) ^0
</code></pre>
<p>一个范围指定了范围的<em>“开始”</em>和<em>“末尾”</em>。 范围是左闭右开的,也就是说范围包含<em>“开始”</em>,不包含<em>“末尾”</em>。<br>
范围 <code></code>、<code></code>和 <code>[..]</code> 都表示整个范围。</p>
<br>
<blockquote>
<p>作者 : John Demetriou<br>
译者 : 技术译民<br>
出品 : 技术译站<br>
链接 : 英文原文</p>
</blockquote>
<hr class="footnotes-sep">
<section class="footnotes">
<ol class="footnotes-list">
<li id="fn1" class="footnote-item"><p>https://www.cnblogs.com/ittranslator/p/13810800.html <code>System.Index</code> 结构体和 Hat 运算符(^)的全新用法 ↩︎ ↩︎</p>
</li>
<li id="fn2" class="footnote-item"><p>https://docs.microsoft.com/zh-cn/dotnet/api/system.span-1 <code>Span&lt;T&gt;</code> ↩︎</p>
</li>
<li id="fn3" class="footnote-item"><p>https://docs.microsoft.com/zh-cn/dotnet/api/system.readonlyspan-1 <code>ReadOnlySpan&lt;T&gt;</code> ↩︎</p>
</li>
<li id="fn4" class="footnote-item"><p>https://docs.microsoft.com/zh-cn/dotnet/api/system.index<code>System.Index</code> ↩︎</p>
</li>
<li id="fn5" class="footnote-item"><p>https://docs.microsoft.com/zh-cn/dotnet/api/system.range<code>System.Range</code> ↩︎</p>
</li>
</ol>
</section>


</div>
<div id="MySignature" role="contentinfo">
    <div><p style="font-size: 14px; font-family: '微软雅黑';font-weight: 400; padding: 0 0 5px 2px;color:#888;">&copy; 转载请标明出处 &nbsp; https://www.cnblogs.com/ittranslator</p></div>
<div style="text-align: center;max-width: 280px;margin: 10px auto;">
   <p style="font-size: 18px; font-weight: 600; color: rgba(0, 0, 0, 1); padding-top: 6px; padding-bottom: 6px; border-bottom: 1px dashed rgba(119, 119, 255, 1)">不做标题党,只分享技术干货
   </p><p style="font-size: 13px; font-weight: 400; padding-top: 6px; padding-bottom: 0px;color:rgb(66,66,166);">公众号『技术译站』,<b>欢迎扫码关注</b></p>
   <img style="width: 215px;" src="https://img2020.cnblogs.com/blog/2074831/202006/2074831-20200628152541133-1651846078.jpg" alt="">
</div><br><br>
来源:https://www.cnblogs.com/ittranslator/p/13800588.html
頁: [1]
查看完整版本: C# 中 System.Range 结构体