.net Substring()
类中System.String
方法的定义就像这样
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]抛出异常?
该字符串有3个字符,因此索引为[0, 1, 2]
,甚至ToArray()
,ToCharArray()
方法按预期返回3个字符!如果我尝试Substring()
使用起始索引3
?
答案 0 :(得分:51)
documentation非常清楚这是正确的行为:
返回值:一个字符串,相当于在此实例中以startIndex开头的子字符串,或 如果startIndex等于此实例的长度,则为空。 < / p>
如果
ArgumentOutOfRangeException
小于零或 *大于此实例的长度,则抛出startIndex
。 * 强>
换句话说,从最后一个字符开始的子字符串将为您提供一个空字符串。
您希望它为您提供字符串的部分的评论与此不相容。 “字符串的一部分”也包括零长度的所有子串的集合,s.substring(n, 0)
将也给出一个空字符串这一事实证明了这一点。
答案 1 :(得分:23)
这里有很多技术答案说明框架如何处理方法调用,但是我想通过类比为为什么给出一个推理。
将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 string
开头的n
个面板。请注意,字符串的最后一个字符后面有一个围栅栏。使用此fence post调用该函数会返回一个值,表明此点后没有fence面板(即返回空string
)。
同样,string.Substring(n, l)
会以fencepost string
开头,返回l
个n
个面板。这就是"ABC".Substring(2, 0)
之类的内容也会返回""
的原因。
答案 2 :(得分:12)
Sometimes looking at the code can be handy:
首先这叫做:
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);
}
答案 3 :(得分:4)
根据MSDN上的内容:
*
返回值 - 一个字符串,相当于在此实例中以startIndex开头的子字符串,如果startIndex等于此实例的长度,则为Empty。
<强>例外强> ArgumentOutOfRangeException - startIndex小于零或大于此实例的长度
*
答案 4 :(得分:4)
查看String.Substring Method文档,如果起始索引等于长度,将返回一个空字符串。
一个字符串,它等于长度为length的子字符串 在此实例中从startIndex开始,如果startIndex相等则为Empty 到这个实例的长度,长度为零。
答案 5 :(得分:2)
Substring的作用是检查startIndex是否大于字符串的长度,然后它才会抛出异常。在你的情况下,它是相等的(字符串长度是3)。之后,它检查子串的长度是否为零,如果返回String.Empty。在您的情况下,子字符串的长度是字符串(3)的长度减去startIndex(3)。这就是子串的长度为0并返回空字符串的原因。
答案 6 :(得分:1)
C#中的所有字符串最后都有String.Empty
。
Here is good answer关于这个问题。
来自MSDN - String
班级(系统):
在.NET Framework中,String对象可以包含嵌入的null 字符,计算为字符串长度的一部分。但是,在 某些语言,如C和C ++,空字符表示结束 一串;它不被认为是字符串的一部分而不是 算作字符串长度的一部分。
答案 7 :(得分:1)
为了补充其他答案,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。