1.String分配了之后就无法更改?
下面的代码会造成编译错误:
string
s
=
"
hello
"
;
s[ 0 ] = ' a ' ;
s[ 0 ] = ' a ' ;
会造成:
Error 3 Property or indexer 'string.this[int]' cannot be assigned to -- it is read only
事实上是可以改变的:
unsafe
{
string s = " hello " ;
fixed ( char * p1 = s)
{
* p1 = ' a ' ;
}
}
{
string s = " hello " ;
fixed ( char * p1 = s)
{
* p1 = ' a ' ;
}
}
2.String不能用new来构造?
由于代码
string
s
=
new
string
(
"
hello
"
);
会报错,没有此类ctor但是实际上string有8个ctor:
public
String(
char
*
value);
public String( char [] value);
public String( sbyte * value);
public String( char c, int count);
public String( char * value, int startIndex, int length);
public String( char [] value, int startIndex, int length);
public String( sbyte * value, int startIndex, int length);
public String( sbyte * value, int startIndex, int length, Encoding enc);
public String( char [] value);
public String( sbyte * value);
public String( char c, int count);
public String( char * value, int startIndex, int length);
public String( char [] value, int startIndex, int length);
public String( sbyte * value, int startIndex, int length);
public String( sbyte * value, int startIndex, int length, Encoding enc);
3.字符串“+”会生成新的字符串?
string
s
=
"
he
"
+
"
ll
"
+
"
o
"
;
看看IL:
IL_0000:
nop
IL_0001: ldstr " hello "
IL_0006: stloc.0
IL_0007: ret
IL_0001: ldstr " hello "
IL_0006: stloc.0
IL_0007: ret
事实上是一个字符串,编译器做了我们不知道的事情。
4.StringBuilder为什么会比String性能好?
String s
=
null
;
for ( int i = 0 ; i < 100 ; i ++ )
s += i.ToString();
for ( int i = 0 ; i < 100 ; i ++ )
s += i.ToString();
+实际调用的是String的静态方法public static string Concat(string str0, string str1)
public
static
string
Concat(
string
str0,
string
str1)
{
if (IsNullOrEmpty(str0))
{
if (IsNullOrEmpty(str1))
{
return Empty;
}
return str1;
}
if (IsNullOrEmpty(str1))
{
return str0;
}
int length = str0.Length;
string dest = FastAllocateString(length + str1.Length);
FillStringChecked(dest, 0 , str0);
FillStringChecked(dest, length, str1);
return dest;
}
{
if (IsNullOrEmpty(str0))
{
if (IsNullOrEmpty(str1))
{
return Empty;
}
return str1;
}
if (IsNullOrEmpty(str1))
{
return str0;
}
int length = str0.Length;
string dest = FastAllocateString(length + str1.Length);
FillStringChecked(dest, 0 , str0);
FillStringChecked(dest, length, str1);
return dest;
}
下面的代码:
StringBuilder sb
=
new
StringBuilder();
for ( int i = 0 ; i < 100 ; i ++ )
sb.Append(i.ToString());
for ( int i = 0 ; i < 100 ; i ++ )
sb.Append(i.ToString());
Append(String)方法:
public
StringBuilder Append(
string
value)
{
if (value != null )
{
string stringValue = this .m_StringValue;
IntPtr currentThread = Thread.InternalGetCurrentThread();
if ( this .m_currentThread != currentThread)
{
stringValue = string .GetStringForStringBuilder(stringValue, stringValue.Capacity);
}
int length = stringValue.Length;
int requiredLength = length + value.Length;
if ( this .NeedsAllocation(stringValue, requiredLength))
{
string newString = this .GetNewString(stringValue, requiredLength);
newString.AppendInPlace(value, length);
this .ReplaceString(currentThread, newString);
}
else
{
stringValue.AppendInPlace(value, length);
this .ReplaceString(currentThread, stringValue);
}
}
return this ;
}
{
if (value != null )
{
string stringValue = this .m_StringValue;
IntPtr currentThread = Thread.InternalGetCurrentThread();
if ( this .m_currentThread != currentThread)
{
stringValue = string .GetStringForStringBuilder(stringValue, stringValue.Capacity);
}
int length = stringValue.Length;
int requiredLength = length + value.Length;
if ( this .NeedsAllocation(stringValue, requiredLength))
{
string newString = this .GetNewString(stringValue, requiredLength);
newString.AppendInPlace(value, length);
this .ReplaceString(currentThread, newString);
}
else
{
stringValue.AppendInPlace(value, length);
this .ReplaceString(currentThread, stringValue);
}
}
return this ;
}
通过比较:
string是每次拼接后都需要分配空间,并返回新string的引用。而StringBulder则是预分配空间,而当字符串拼接时,则先检查字符串的空间,再决定是否需要分配新空间。向堆上申请内存空间是比较耗时的操作。