C#中子字符串的意外行为
.net System.String
类中的Substring()
方法的定义是这样的
public string Substring(int startIndex)
其中startIndex
是根据方法定义的“此实例中子字符串从零开始的起始字符位置” 。 如果我理解正确,这意味着它将给我一部分字符串,从给定的从零开始的索引开始。
现在,如果我有一个字符串"ABC"
并使用不同索引的子字符串,我得到以下结果。
var str = "ABC"; var chars = str.ToArray(); //returns 3 char 'A', 'B', 'C' as expected var sub2 = str.Substring(2); //[1] returns "C" as expected var sub3 = str.Substring(3); //[2] returns "" ...!!! Why no exception?? var sub4 = str.Substring(4); //[3] throws ArgumentOutOfRangeException as expected
为什么它不会为案例[2]抛出exception?
该字符串有3个字符,所以索引是[0, 1, 2]
,甚至ToArray()
, ToCharArray()
方法返回3个字符! 如果我尝试使用起始索引3
Substring()
,它不应该抛出exception吗?
文档非常清楚这是正确的行为:
返回值:一个字符串,相当于在此实例中以startIndex开头的子字符串, 如果startIndex等于此实例的长度,则为Empty。
如果
startIndex
小于零或*大于此实例的长度,则抛出ArgumentOutOfRangeException
。 *
换句话说,从最终字符之外开始的子字符串将为您提供一个空字符串。
您希望它给您一部分字符串的评论与此不相容。 “字符串的一部分”也包括零长度的所有子串的集合,如s.substring(n, 0)
也将给出空字符串这一事实所certificate。
这里有很多技术答案说这个框架如何处理方法调用,但是我想通过类比给出一个推理, 为什么它就像它一样。
将string
视为栅栏,其中栅栏板本身就是字符,用栅栏柱支撑,编号如下所示:
0 1 2 3 | A | B | C | "ABC" 0 1 2 3 4 5 6 7 8 9 | M | y | | S | t | r | i | n | g | "My String"
在这个类比中, string.Substring(n)
返回一个以fencepost n
开头的面板string
。 请注意,该字符串的最后一个字符后面有一个fence栏。 使用此fence post调用该函数会返回一个值,表明此点之后没有fence面板(即,它返回空string
)。
类似地, string.Substring(n, l)
返回以fencepost n
开头的l
面板的string
。 这就是为什么像"ABC".Substring(2, 0)
这样的东西"ABC".Substring(2, 0)
返回""
。
有时查看代码可能很方便 :
首先这叫做:
public string Substring(int startIndex) { return this.Substring(startIndex, this.Length - startIndex); }
由于减值,长度为0:
public string Substring(int startIndex, int length) { if (startIndex < 0) { throw new ... } if (startIndex > this.Length) { throw new ... } if (length < 0) { throw new ... } if (startIndex > (this.Length - length)) { throw new ... } if (length == 0) // <-- NOTICE HERE { return Empty; } if ((startIndex == 0) && (length == this.Length)) { return this; } return this.InternalSubString(startIndex, length); }
根据MSDN上写的内容:
*
返回值 – 一个字符串,它等于在此实例中以startIndex开头的子字符串,如果startIndex等于此实例的长度,则为Empty。
exception ArgumentOutOfRangeException – startIndex小于零或大于此实例的长度
*
查看String.Substring方法文档,如果起始索引等于长度,将返回空字符串。
一个字符串,它等于在此实例中以startIndex开头的长度长度的子字符串,如果startIndex等于此实例的长度且长度为零,则为Empty。
Substring的作用是检查startIndex是否大于字符串的长度,然后它才会抛出exception。 在你的情况下它是相等的(字符串长度是3)。 之后,它检查子串的长度是否为零,如果返回String.Empty。 在您的情况下,子字符串的长度是字符串(3)的长度减去startIndex(3)。 这就是子串的长度为0并返回空字符串的原因。
C#中的所有字符串最后都有String.Empty
。
这个问题的答案很好 。
从MSDN – String
类(系统):
在.NET Framework中,String对象可以包含嵌入的空字符,这些字符计为字符串长度的一部分。 但是,在某些语言(如C和C ++)中,空字符表示字符串的结尾; 它不被视为字符串的一部分,不计入字符串长度的一部分。
为了补充其他答案,Mono也正确地实现了这种行为。
public String Substring (int startIndex) { if (startIndex == 0) return this; if (startIndex < 0 || startIndex > this.length) throw new ArgumentOutOfRangeException ("startIndex"); return SubstringUnchecked (startIndex, this.length - startIndex); } // This method is used by StringBuilder.ToString() and is expected to // always create a new string object (or return String.Empty). internal unsafe String SubstringUnchecked (int startIndex, int length) { if (length == 0) return String.Empty; string tmp = InternalAllocateStr (length); fixed (char* dest = tmp, src = this) { CharCopy (dest, src + startIndex, length); } return tmp; }
如您所见,如果长度等于零,则返回String.Empty。
上述就是C#学习教程:C#中子字符串的意外行为分享的全部内容,如果对大家有所用处且需要了解更多关于C#学习教程,希望大家多多关注---计算机技术网(www.ctvol.com)!
本文来自网络收集,不代表计算机技术网立场,如涉及侵权请联系管理员删除。
ctvol管理联系方式QQ:251552304
本文章地址:https://www.ctvol.com/cdevelopment/985223.html