Int [] é um tipo de referência ou um tipo de valor?


124

Eu sei que int é um tipo de valor, mas o que são matrizes de tipos de valor? Tipos de referência? Tipos de valor? Eu quero passar uma matriz para uma função para verificar alguma coisa. Devo apenas passar a matriz, pois passará apenas a referência, ou devo passar como ref?


11
No futuro, você pode verificar se algo é passado por referência ou por valor criando uma variável, passando essa variável para um método que a altera e verificando qual é o valor dessa variável depois de executada pelo método. Se é o mesmo, é passado por valor, diferente, passado por referência.

11
@ darkassassin93: A passagem por referência ou por valor não tem relação com o fato de algo ser um tipo de referência ou um valor. (Tipos de valor podem ser passados por referência e tipos de referência pode ser passado por valor.)
LukeH

2
Na maioria dos casos, se você pode armazenar [nulo] dentro de um campo ou variável, pode assumir que é um tipo de referência. As exceções certamente são tipos anuláveis ​​(Nullable <int> ou int?), Além de strings.
quer

3
@ NoëlWidmer Strings não são uma exceção: são tipos de referência.
Arthur Castro

2
@ArthurCastro Concorde com 50%: as seqüências herdam da classe, o que significa que são tipos de referência. No entanto, sua igualdade é baseada na identidade (comparação de valores), e não na referência, e seu comportamento de aprovação é anulado para corresponder ao comportamento dos tipos de valor. Basicamente, eles são tipos de referência por definição, mas se comportam mais como tipos de valor por implementação.
27628 Noel Widmer

Respostas:


201

Matrizes são mecanismos que permitem tratar vários itens como uma única coleção. O Microsoft® .NET Common Language Runtime (CLR) suporta matrizes unidimensionais, matrizes multidimensionais e matrizes irregulares (matrizes de matrizes). Todos os tipos de matriz são derivados implicitamente de System.Array, que é derivado de System.Object. Isso significa que todas as matrizes são sempre tipos de referência alocadas no heap gerenciado e a variável do seu aplicativo contém uma referência à matriz e não à própria matriz.

https://msdn.microsoft.com/en-us/library/bb985948.aspx


54
Os tipos de valor herdam de System.ValueType, que herda de System.Object. Portanto, apenas porque Array deriva de System.Object não significa que é um tipo de referência. O que faz do System.Array um tipo de referência é que suas instâncias são copiadas por referência. IOW, concentre-se no fato de que System.Array é uma classe. É isso que o torna um tipo de referência.
P.Brian.Mackey

8
<nitpick> Eu sei que pode parecer que a documentação está implicando que System.Array derivado de System.Object o torna um tipo de referência. Embora possa não ser verdade que qualquer tipo derivado de System.Object seja um tipo de referência, a única exceção a essa regra é System.ValueType, que é tratado de forma diferente pelo compilador. </nitpick>
Yannick Motton -

O link acima está quebrado. Aqui está outro link MSDN que mostra a hierarquia de herança de System.Array: msdn.microsoft.com/de-de/library/system.array(v=vs.110).aspx
MUG4N

Tudo o que deriva de System.Object é um tipo de referência, a menos que também derive de System.ValueType. @ P.Brian.Mackey apenas porque um tipo é uma classe, não significa que é um tipo de referência, porque nos bastidores, estruturas são apenas classes que derivam de System.ValueType.
David Klempfner

31

O teste mais simples para o tipo de referência versus o tipo de valor é que os tipos de referência podem ser null, mas os tipos de valor não.


46
... exceto para os tipos de valores anuláveis, que são anuláveis ​​(você pode definir o valor como nulo, o que significa o valor nulo para o tipo em vez de uma referência nula ) e ainda são tipos de valores.
9139 Jon Skeet

1
Nunca pensei em fazer isso ao tentar entender se são tipos de valor ou não! Boa ideia.
elísio devorado


6

Primeiro, quero lhe dizer que a matriz é um tipo de referência. Por quê? Eu explico dar um exemplo aqui.

Exemplo:

int val = 0; // this is a value type ok
int[] val1 = new int[20] // this is a reference type because space required to store 20 integer value that make array allocated on the heap.

Os tipos de referência também podem ser nulos, enquanto os tipos de valor não podem.

tipo de valor armazenado em Stack e tipo de referência armazenado em Heap

Você pode passar o array para funcionar usando out ou ref. Apenas os métodos de inicialização são diferentes.

Mais..


3

Teste para verificar se é um tipo de referência ou valor:

// we create a simple array of int
var a1 = new int[]{1,2,3};
// copy the array a1 to a2
var a2 = a1;
// modify the first element of a1
a1[0]=2;
// output the first element of a1 and a2
Console.WriteLine("a1:"+a1[0]); // 2
Console.WriteLine("a2:"+a2[0]); // 2
//**************************
// all the two variable point to the same array
// it's reference type!
//**************************

Você pode testá-lo on-line: https://dotnetfiddle.net/UWFP45


2
Seria mais fácil criar uma matriz e tentar atribuí-la a null. Compilação falharia se fosse um tipo de valor ..
Elysium devorado

Esteja avisado. Depois que o C # 8 for lançado, ele também falhará se você estiver usando o recurso de tipos de referência anuláveis, pois os tipos de referência não anuláveis ​​também não podem aceitar nulos.
Mark-Donohoe

2

A matriz em si é um tipo de referência. Os valores dessa matriz são tipos de valor ou referência, conforme determinado pelo tipo de dados da matriz. No seu exemplo, a matriz é um tipo de referência e os valores são tipos de valores.

Todas as matrizes de dimensão única são implementadas implicitamente IList<T>, onde <T>é o tipo de dados da matriz. Você pode usar essa interface como o tipo de dados do seu parâmetro de método. Você também pode usar IEnumerable<T>para o tipo de dados. Em qualquer um dos casos (ou mesmo se você acabou de usar int[]), você não precisa passá-lo explicitamente como refparâmetro.


0

// A referência à matriz é passada por valor. Esta é a fonte da confusão :-) ...

        int[] test = { 1, 2, 3, 4 };

        modifContenuSansRef(test);
        Console.WriteLine(test[0]); // OK --> 99 le contenu du tableau est modifié

        modifTailleSansRef(test);
        Console.WriteLine(test.Length); // KO --> 4 La taille n'est pas modifiée

    }

    static void modifContenuSansRef(int[] t)
    {
        t[0] = 99;
    }

    static void modifTailleSansRef(int[] t)
    {
        Array.Resize(ref t, 8);
    }

0

As matrizes sempre são tipos de referência. Não importa que a matriz contenha um tipo de valor como int ou um tipo de referência como string. Quando você declara a matriz por exemplo

int[] integers=new int[10];

A própria variável de inteiros contém apenas referência à matriz que residirá na pilha.

Também existem muitas pessoas que mencionam que você pode diferir o tipo de valor do tipo de referência, dependendo apenas do fato de a variável ser nula ou não. Eu gostaria de mencionar que no c # atualmente os tipos de valor também podem ser nulos

por exemplo

int? integer=null

e não é uma boa maneira de identificar que o tipo é referência ou valor depende apenas do fato de a variável poder ser nula ou não.


-2

Apenas um pouco de uma visão:

Por exemplo, intrepresenta um único número inteiro,int[] representa uma matriz de números inteiros.

Para inicializar a matriz com dimensões específicas, você pode usar a newpalavra - chave, fornecendo o tamanho entre colchetes após o nome do tipo:

//create a new array of 32 ints.
int[] integers = new int[32];

Todas as matrizes são tipos de referência e seguem a semântica de referência. Portanto, nesse código, mesmo que os elementos individuais sejam tipos de valores primitivos, a integersmatriz é um tipo de referência. Então, se você escrever mais tarde:

int[] copy = integers;

isso simplesmente atribuirá toda a cópia da variável para se referir à mesma matriz, não criará uma nova matriz.

A sintaxe da matriz do C # é flexível, permite declarar matrizes sem inicializá-las, para que a matriz possa ser dimensionada dinamicamente posteriormente no programa. Com essa técnica, você basicamente cria uma referência nula e depois aponta essa referência em um trecho de locais de memória alocado dinamicamente, solicitado com umnew palavra-chave:

int[] integers;
integers = new int[32];

Obrigado.

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.