Pergunta

A partir de um olhar breve com refletor, parece que a memória String.Substring() aloca para cada substring. Estou correto que este é o caso? Eu pensei que não seria necessário uma vez que strings são imutáveis.

Meu objetivo subjacente era criar um método de extensão IEnumerable<string> Split(this String, Char) que aloca nenhuma memória adicional.

Foi útil?

Solução

Uma razão pela qual a maioria das línguas com cordas imutáveis ??criar novas substrings em vez de se referir em cadeias existentes é porque isso irá interferir com a coleta de lixo aquelas cordas mais tarde.

O que acontece se uma string é utilizado para a sua substring, mas então a seqüência maior se torna inacessível (exceto através da substring). A seqüência maior será incobrável, porque isso iria invalidar a substring. O que parecia uma boa maneira de poupar memória a curto prazo torna-se uma fuga de memória a longo prazo.

Outras dicas

não é possível sem picar ao redor dentro .net usando classes de corda. Você teria que passar em torno de referências para uma matriz que era mutável e garantir que ninguém asneira.

Net irá criar uma nova seqüência cada vez que você pedir para ele. Única exceção a isso é internado cordas que são criados pelo compilador (e pode ser feito por você), que são colocados na memória uma vez e, em seguida, os ponteiros são estabelecidos para a cadeia por razões de memória e desempenho.

Cada corda tem que ter é dados próprios de cordas, com a maneira que a classe String é implementado.

Você pode fazer a sua própria estrutura SubString que utiliza parte de uma 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);
   }

}

Você pode completá-lo com outros métodos como comparação que também é possível fazer sem extrair a string.

Porque strings são imutáveis ??em .NET, cada operação de cadeia que resulta em um novo objeto string irá alocar um novo bloco de memória para o conteúdo de string.

Em teoria, poderia ser possível reutilizar a memória quando se extrai um substring, mas que faria a coleta de lixo muito complicada: e se a string original é de lixo coletado? O que aconteceria com o substring que compartilha um pedaço dele?

É claro, nada impede que a equipe .NET BCL para alterar esse comportamento em versões futuras do .NET. Ele não teria qualquer impacto sobre o código existente.

Adicionando a tal ponto que strings são imutáveis, você deve ser que o trecho a seguir irá gerar várias instâncias de String na memória.

String s1 = "Hello", s2 = ", ", s3 = "World!";
String res = s1 + s2 + s3;

s1 + s2 => nova instância string (temp1)

temp1 + s3 => nova instância string (temp2)

res é uma referência para temp2. ??

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top