最近看到好几篇,关于string的文章,有的说的不错,有的则说的有点问题,所以,干脆也来谈谈string的问题。
1、string是引用类型,这个事实的证明方法有很多,例如:
Console.WriteLine(typeof(string).IsValueType);// false
string s = "some string";
Console.WriteLine(object.ReferenceEquals(s, s));// true, no boxing
Console.WriteLine(object.ReferenceEquals(1, 1));// false, boxing
string s = "some string";
Console.WriteLine(object.ReferenceEquals(s, s));// true, no boxing
Console.WriteLine(object.ReferenceEquals(1, 1));// false, boxing
2、string是不可改变的。关于这一点,我持反对意见,string绝对是可以改变的,只不过,一般情况下不需要去改变string本身,就可以达到目的,例如使用string.Concat方法(也就是“+”的真正实现)
方法1 - unsafe代码:
string s = "some string";
unsafe
{
fixed (char* ptr = s)
{
*ptr = 'S';
}
}
Console.WriteLine(s);
unsafe
{
fixed (char* ptr = s)
{
*ptr = 'S';
}
}
Console.WriteLine(s);
方法2 - 反射(调用那些本来应该由StringBuilder来调用的方法):
string s = "some string";
typeof(string).GetMethod("SetChar", BindingFlags.Instance | BindingFlags.NonPublic).Invoke(s, new object[] { 0, 'S' });
Console.WriteLine(s);
typeof(string).GetMethod("SetChar", BindingFlags.Instance | BindingFlags.NonPublic).Invoke(s, new object[] { 0, 'S' });
Console.WriteLine(s);
3、string的安全性。为了保证敏感信息的安全,请尽量使用System.Security.SecureString,当然,如果你喜欢玩弄string的话,也不是完全没有办法,只需要稍微动点手脚,就可以让真实的string(“你好”)仅仅在需要的那一刻出现,平时则伪装成“企夜”,来欺骗那些试图直接读取内存的程序:
string s = "企夜";
unsafe // decode
{
fixed (char* ptr = s)
for (int i = 0; i < s.Length; i++)
*(ptr + i) ^= 'a';
}
Console.WriteLine(s);
unsafe // re-encode
{
fixed (char* ptr = s)
for (int i = 0; i < s.Length; i++)
*(ptr + i) ^= 'a';
}
Console.WriteLine(s);
unsafe // decode
{
fixed (char* ptr = s)
for (int i = 0; i < s.Length; i++)
*(ptr + i) ^= 'a';
}
Console.WriteLine(s);
unsafe // re-encode
{
fixed (char* ptr = s)
for (int i = 0; i < s.Length; i++)
*(ptr + i) ^= 'a';
}
Console.WriteLine(s);
其实还可以写的更诡异:
unsafe // decode
{
fixed (char* ptr = "企夜")
for (int i = 0; i < "企夜".Length; i++)
*(ptr + i) ^= 'a';
}
Console.WriteLine("企夜");
unsafe // re-encode
{
fixed (char* ptr = "企夜")
for (int i = 0; i < "企夜".Length; i++)
*(ptr + i) ^= 'a';
}
Console.WriteLine("企夜");
{
fixed (char* ptr = "企夜")
for (int i = 0; i < "企夜".Length; i++)
*(ptr + i) ^= 'a';
}
Console.WriteLine("企夜");
unsafe // re-encode
{
fixed (char* ptr = "企夜")
for (int i = 0; i < "企夜".Length; i++)
*(ptr + i) ^= 'a';
}
Console.WriteLine("企夜");