Pergunta

A String é um tipo de referência, mesmo que tem a maioria das características de um tipo de valor como ser imutável e tendo == sobrecarregado para comparar o texto, em vez de ter certeza que eles fazem referência ao mesmo objeto.

Por que não é seqüência de apenas um tipo de valor, então?

Foi útil?

Solução

Cordas não são tipos de valor, uma vez que pode ser enorme, e precisam ser armazenados na pilha. Tipos de valor são (em todas as implementações do CLR como de ainda) armazenados na pilha. Empilhar alocação de cordas iria quebrar todos os tipos de coisas: a pilha é de apenas 1MB de 32 bits e 4MB de 64 bits, você teria de caixa cada corda, incorrer em uma penalidade cópia, você poderia cordas não internos, e uso de memória seria balão, etc ...

(Edit: Adicionado esclarecimentos sobre o armazenamento tipo de valor a ser um detalhe de implementação, o que leva a esta situação onde temos um tipo com sematics valor não herdando de System.ValueType Graças Ben..)

Outras dicas

Não é um tipo de valor porque o desempenho (espaço e tempo!) Seria terrível se fosse um tipo de valor e seu valor teve de ser copiado cada vez que foram passados ??para e retornados de métodos, etc.

Tem semântica de valor para manter a sanidade mundo. Você pode imaginar o quão difícil seria a de código se

string s = "hello";
string t = "hello";
bool b = (s == t);

set b ser false? Imagine o quão difícil codificação de praticamente qualquer aplicação seria.

A distinção entre tipos de referência e tipos de valor são basicamente uma troca desempenho no projeto da linguagem. tipos de referência tem alguma sobrecarga na construção e destruição e coleta de lixo, porque eles são criados na pilha. tipos de valor, por outro lado tem sobrecarga de chamadas de método (se o tamanho dos dados é maior do que um ponteiro), porque todo o objeto é copiado em vez de apenas um ponteiro. Porque cordas podem ser (e geralmente são) muito maior do que o tamanho de um ponteiro, que são concebidos como tipos de referência. Além disso, como Servy apontou, do tamanho de um tipo de valor deve ser conhecido em tempo de compilação, o que nem sempre é o caso de strings.

A questão da mutabilidade é uma questão separada. Ambos os tipos de referência e tipos de valor podem ser mutáveis ??ou imutáveis. Tipos de valor são embora normalmente imutável, uma vez que a semântica para tipos de valores mutáveis ??pode ser confuso.

tipos de

Referência geralmente são mutáveis, mas pode ser concebido como imutável se faz sentido. Cordas são definidos como imutável porque faz determinadas otimizações possível. Por exemplo, se o mesmo literal de cadeia ocorre várias vezes no mesmo programa (que é bastante comum), o compilador pode reutilizar o mesmo objeto.

Então, porque é "==" sobrecarregado para comparar strings por texto? Porque ele é o mais semântica úteis. Se duas strings são iguais pelo texto, que pode ou não ser a mesma referência de objeto devido às otimizações. Assim referências comparando são bastante inútil, enquanto comparando texto são quase sempre o que você quer.

Falando em termos mais gerais, Cordas tem o que é chamado semântica de valor . Este é um conceito mais geral do que os tipos de valor, que é um C # implementação específica detalhes. Tipos de valor têm semântica de valor, mas os tipos de referência também podem ter valores semânticos. Quando um tipo de ter semântica de valor, você não pode realmente dizer se a implementação subjacente é um tipo de referência ou valor de tipo, então você pode considerar que um detalhe de implementação.

Esta é uma resposta final a uma questão de idade, mas todas as outras respostas estão faltando o ponto, o que é que o .NET não têm genéricos até .NET 2.0 em 2005.

String é um tipo de referência, em vez de um tipo de valor, porque que era de importância crucial para a Microsoft para garantir que as cordas podem ser armazenados da maneira mais eficiente em coleções não-genéricos , tais como System.Collection.ArrayList.

Como armazenar um tipo de valor em uma coleção não genérico requer uma conversão especial para o tipo object que é chamado de boxe. Quando as caixas CLR um tipo de valor, que envolve o valor dentro de um System.Object e armazena-o no heap gerenciado.

A leitura do valor da coleção requer a operação inversa, que é chamado unboxing.

Ambos boxing e unboxing tem custo não negligenciável: o boxe exige uma dotação adicional, unboxing exige a verificação de tipo

.

Algumas respostas afirmam incorretamente que string nunca poderia ter sido implementado como um tipo de valor, porque seu tamanho é variável. Na verdade, é fácil de implementar cadeia como uma estrutura de dados de comprimento fixo utilizando uma estratégia de cadeia pequena Optimização: cordas seria armazenado na memória directamente como uma sequência de caracteres Unicode excepto para grandes cadeias que seriam armazenados como um apontador para um tampão externo. Ambas as representações podem ser projetados para ter o mesmo comprimento fixo, ou seja, o tamanho de um ponteiro.

Se os genéricos já existia desde o primeiro dia que eu acho que ter cadeia como um tipo de valor provavelmente teria sido uma solução melhor, com a semântica mais simples, uso de memória melhor e melhor localidade cache. A List<string> contendo apenas pequenas cordas poderia ter sido um único bloco contíguo de memória.

Não só cordas são tipos de referência imutáveis. delegados Multi-elenco também. É por isso que ele é seguro para escrever

protected void OnMyEventHandler()
{
     delegate handler = this.MyEventHandler;
     if (null != handler)
     {
        handler(this, new EventArgs());
     }
}

Suponho que strings são imutáveis, porque este é o método mais seguro para trabalhar com eles e alocar memória. Por que eles não são tipos de valor? autores anteriores está certo sobre o tamanho da pilha etc. Gostaria de acrescentar também que fazer cordas uma referência tipos permitem economizar no tamanho de montagem quando você usa a mesma string constante no programa. Se você definir

string s1 = "my string";
//some code here
string s2 = "my string";

As possibilidades são que ambas as instâncias do constante "minha string" serão alocados em sua montagem somente uma vez.

Se você gostaria de gerenciar strings como tipo de referência de costume, coloque a palavra dentro de um novo StringBuilder (string s). Ou use MemoryStreams.

Se você está a criar uma biblioteca, onde se espera um enorme cordas para ser passado em suas funções, ou definir um parâmetro como um StringBuilder ou como um Stream.

Além disso, a forma como as cordas são implementadas (diferente para cada plataforma) e quando você começar a costurá-las juntas. Como usar um StringBuilder. Ele allocats um buffer para você copiar para, uma vez que você chegar ao fim, ele aloca ainda mais memória para você, na esperança de que se você fizer um grande desempenho concatenação não será prejudicada.

Talvez Jon Skeet pode ajudar até aqui?

É principalmente um problema de desempenho.

Tendo cordas comportar como tipo de valor ajuda ao escrever código, mas tê-lo ser um tipo de valor faria um desempenho enorme sucesso.

Para um olhar em profundidade, dar uma olhada em um belo artigo em strings no quadro.

Como você pode dizer string é um tipo de referência? Eu não tenho certeza que isso importe como ele é implementado. Cordas em C # são imutáveis, precisamente para que você não precisa se preocupar com esta questão.

Na verdade cordas têm muito poucas semelhanças com tipos de valor. Para começar, nem todos os tipos de valor são imutáveis, você pode alterar o valor de um Int32 tudo o que você quer e ele ainda seria o mesmo endereço na pilha.

Strings são imutáveis ??por uma razão muito boa, não tem nada a ver com ele ser um tipo de referência, mas tem muito a ver com o gerenciamento de memória. É apenas mais eficiente para criar um novo objeto quando o tamanho do seqüência de mudanças do que as coisas mudam de lugar no heap gerenciado. Eu acho que você está misturando valor juntamente / tipos de referência e conceitos objetos imutáveis.

Tanto quanto "==":. Como você disse "==" é uma sobrecarga do operador, e novamente ele foi implementado por uma boa razão para quadro make mais útil quando se trabalha com cordas

Em uma forma muito simples palavras qualquer valor que tem um tamanho definido podem ser tratados como um tipo de valor.

Não é tão simples como cordas são feitas de personagens matrizes. Eu olho para strings como arrays de caracteres []. Portanto, eles são na pilha porque o local da memória de referência é armazenado na pilha e aponta para o início do local de memória da matriz na pilha. O tamanho cadeia não é conhecido antes de ser alocado ... perfeito para o heap.

É por isso que uma string é realmente imutável porque quando você alterá-la, mesmo que seja do mesmo tamanho que o compilador não sabe que e tem que alocar uma nova matriz e personagens atribuir às posições na matriz. Faz sentido se você pensar em cadeias como uma maneira que as línguas protegê-lo de ter que alocar memória na mosca (leia-C como programação)

Com o risco de ficar mais um down-voto misteriosa ... o fato de que muitos menção a pilha e memória em relação a tipos de valor e tipos primitivos é porque eles devem caber em um registo no microprocessador. Você não pode empurrar ou pop algo de / para a pilha se leva mais bits do que um registo tem .... as instruções são, por exemplo "eax pop" - porque eax é de 32 bits de largura em um sistema de 32 bits <. / p>

de ponto flutuante tipos primitivas são tratadas pelo FPU, que é de 80 bits de largura.

Isto foi tudo decidido muito antes de existir uma linguagem OOP para ofuscar a definição de tipo primitivo e suponho que tipo de valor é um termo que foi criado especificamente para linguagens OOP.

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