从使用反射简单的介绍一下,它看起来像String.Substring()
对每个子分配内存。 我是正确,这是这种情况? 我想,既然string是不可改变的,不会是必要的。
我的基本目标是创建一个IEnumerable<string> Split(this String, Char)
,其分配没有额外的存储器扩展方法。
从使用反射简单的介绍一下,它看起来像String.Substring()
对每个子分配内存。 我是正确,这是这种情况? 我想,既然string是不可改变的,不会是必要的。
我的基本目标是创建一个IEnumerable<string> Split(this String, Char)
,其分配没有额外的存储器扩展方法。
原因之一,不可变的字符串大多数语言创建新的子串,而不是指到现有的字符串是因为这将与后来的垃圾收集这些字符串干扰。
如果用于其子字符串会发生什么,但随后的大串变得无法访问(除非通过子)。 较大的字符串将是无法收回的,因为那会无效子。 什么似乎是一个很好的方式,以节省内存在短期内成为一个长期的内存泄漏。
不可能没有内部.NET中使用字符串类打交道了。 你将不得不绕过这是可变的一个数组引用,并确保没有人搞砸了。
.NET将创建一个新的字符串每次你问它的时间。 唯一的例外,这是扣留这是由编译器创建(可以由您来完成)被放置到内存中一次,然后指针确定的字符串内存和性能方面的原因字符串。
每个串都必须有它自己的字符串数据,与String类的实现方式。
你可以使用一个字符串的一部分自己的子结构:
public struct SubString {
private string _str;
private int _offset, _len;
public SubString(string str, int offset, int len) {
_str = str;
_offset = offset;
_len = len;
}
public int Length { get { return _len; } }
public char this[int index] {
get {
if (index < 0 || index > len) throw new IndexOutOfRangeException();
return _str[_offset + index];
}
}
public void WriteToStringBuilder(StringBuilder s) {
s.Write(_str, _offset, _len);
}
public override string ToString() {
return _str.Substring(_offset, _len);
}
}
你可以用其他方法,如对比的是,也可以不提取字符串做割肉出来。
因为字符串.NET是不可变的,这导致新的字符串对象中的每个串操作将分配的内存新块的字符串的内容。
从理论上讲,它可能是可能提取子的时候重新使用的内存,但是这将使垃圾收集非常复杂:如果原始字符串垃圾收集哪些? 会发生什么共享一块它的子?
当然,没有什么可以阻止.NET BCL团队改变.NET的未来版本中此行为。 它不会对现有代码的任何影响。
添加到字符串是不可变的时候,你应该是下面的代码片段会在内存中生成多个字符串实例。
String s1 = "Hello", s2 = ", ", s3 = "World!";
String res = s1 + s2 + s3;
S1 + S2 =>新的字符串实例(temp1目录)
temp1中+ S3 =>新的字符串实例(TEMP2)
RES是为temp2的参考。