Partilhar via


Matrizes

Você pode armazenar várias variáveis do mesmo tipo em uma estrutura de dados de matriz. Você declara uma matriz especificando o tipo de seus elementos. Se desejar que a matriz armazene elementos de qualquer tipo, você pode especificar object como seu tipo. No sistema de tipos unificado de C#, todos os tipos, predefinidos e definidos pelo usuário, tipos de referência e tipos de valor, herdam direta ou indiretamente do Object.

type[] arrayName;

Uma matriz é um tipo de referência, portanto, a matriz pode ser um tipo de referência anulável . Os tipos de elemento podem ser tipos de referência, portanto, uma matriz pode ser declarada para conter tipos de referência anuláveis. As declarações de exemplo a seguir mostram a sintaxe diferente usada para declarar a anulabilidade da matriz ou dos elementos:

type?[] arrayName; // non nullable array of nullable element types.
type[]? arrayName; // nullable array of non-nullable element types.
type?[]? arrayName; // nullable array of nullable element types.

Os elementos não inicializados em uma matriz são definidos como o valor padrão para esse tipo:

int[] numbers = new int[10]; // All values are 0
string[] messages = new string[10]; // All values are null.

Importante

No exemplo anterior, mesmo que o tipo seja string[], uma matriz de cadeias de caracteres não anuláveis, o valor padrão para cada elemento é null. A melhor maneira de inicializar uma matriz para valores não nulos é usar uma expressões de coleção.

Uma matriz tem as seguintes propriedades:

  • Uma matriz pode ser unidimensional, multidimensional ou irregular.
  • O número de dimensões é definido quando uma variável de matriz é declarada. O comprimento de cada dimensão é estabelecido quando a instância da matriz é criada. Esses valores não podem ser alterados durante o tempo de vida da instância.
  • Uma matriz irregular é uma matriz de matrizes, e cada matriz membro tem o valor padrão de null.
  • As matrizes são indexadas zero: uma matriz com n elementos é indexada de 0 até n-1.
  • Os elementos de matriz podem ser de qualquer tipo, incluindo um tipo de matriz.
  • Tipos de matriz são tipos de referência derivados do tipo Arraybase abstrato . Todos os arrays implementam IList e IEnumerable. Você pode usar a instrução foreach para iterar através de uma matriz. Matrizes unidimensionais também implementam IList<T> e IEnumerable<T>.

Os elementos de uma matriz podem ser inicializados para valores conhecidos quando a matriz é criada. A partir do C# 12, todos os tipos de coleção podem ser inicializados usando uma expressão Collection. Os elementos que não são inicializados são definidos com o valor padrão. O valor padrão é o padrão de 0 bits. Todos os tipos de referência (incluindo os tipos não anuláveis ) têm os valores null. Todos os tipos de valor têm os padrões de 0 bits. Isso significa que a Nullable<T>.HasValue propriedade é false e a Nullable<T>.Value propriedade é indefinida. Na implementação do .NET, a Value propriedade lança uma exceção.

O exemplo a seguir cria matrizes unidimensionais, multidimensionais e irregulares:

// Declare a single-dimensional array of 5 integers.
int[] array1 = new int[5];

// Declare and set array element values.
int[] array2 = [1, 2, 3, 4, 5, 6];

// Declare a two dimensional array.
int[,] multiDimensionalArray1 = new int[2, 3];

// Declare and set array element values.
int[,] multiDimensionalArray2 = { { 1, 2, 3 }, { 4, 5, 6 } };

// Declare a jagged array.
int[][] jaggedArray = new int[6][];

// Set the values of the first array in the jagged array structure.
jaggedArray[0] = [1, 2, 3, 4];

Importante

Muitos dos exemplos neste artigo usam expressões de coleção (que usam colchetes) para inicializar as matrizes. As expressões de coleção foram introduzidas pela primeira vez no C# 12, que acompanha o .NET 8. Se você ainda não puder atualizar para C# 12, use { e } inicialize as matrizes.

// Collection expressions:
int[] array = [1, 2, 3, 4, 5, 6];
// Alternative syntax:
int[] array2 = {1, 2, 3, 4, 5, 6};

Matrizes unidimensionais

Uma matriz unidimensional é uma sequência de elementos semelhantes. Você acessa um elemento por meio de seu índice. O índice é a sua posição ordinal na sequência. O primeiro elemento na matriz está no índice 0. Você cria uma matriz unidimensional usando o novo operador especificando o tipo de elemento de matriz e o número de elementos. O exemplo a seguir declara e inicializa matrizes unidimensionais:

int[] array = new int[5];
string[] weekDays = ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"];

Console.WriteLine(weekDays[0]);
Console.WriteLine(weekDays[1]);
Console.WriteLine(weekDays[2]);
Console.WriteLine(weekDays[3]);
Console.WriteLine(weekDays[4]);
Console.WriteLine(weekDays[5]);
Console.WriteLine(weekDays[6]);

/*Output:
Sun
Mon
Tue
Wed
Thu
Fri
Sat
*/

A primeira declaração declara uma matriz não inicializada de cinco inteiros, de array[0] a array[4]. Os elementos da matriz são inicializados com o valor padrão do tipo de elemento, 0 para inteiros. A segunda declaração declara uma matriz de cadeias de caracteres e inicializa todos os sete valores dessa matriz. Uma série de Console.WriteLine instruções imprime todos os elementos da weekDay matriz. Para matrizes unidimensionais, a instrução processa foreach elementos em ordem de índice crescente, começando com o índice 0 e terminando com o índice Length - 1.

Passar matrizes unidimensionais como argumentos

Você pode passar uma matriz unidimensional inicializada para um método. No exemplo a seguir, uma matriz de cadeias de caracteres é inicializada e passada como um argumento para um DisplayArray método para cadeias de caracteres. O método exibe os elementos da matriz. Em seguida, o ChangeArray método inverte os elementos da matriz e, em seguida, o ChangeArrayElements método modifica os três primeiros elementos da matriz. Depois que cada método retorna, o DisplayArray método mostra que passar uma matriz por valor não impede alterações nos elementos da matriz.

class ArrayExample
{
    static void DisplayArray(string[] arr) => Console.WriteLine(string.Join(" ", arr));

    // Change the array by reversing its elements.
    static void ChangeArray(string[] arr) => Array.Reverse(arr);

    static void ChangeArrayElements(string[] arr)
    {
        // Change the value of the first three array elements.
        arr[0] = "Mon";
        arr[1] = "Wed";
        arr[2] = "Fri";
    }

    static void Main()
    {
        // Declare and initialize an array.
        string[] weekDays = ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"];
        // Display the array elements.
        DisplayArray(weekDays);
        Console.WriteLine();

        // Reverse the array.
        ChangeArray(weekDays);
        // Display the array again to verify that it stays reversed.
        Console.WriteLine("Array weekDays after the call to ChangeArray:");
        DisplayArray(weekDays);
        Console.WriteLine();

        // Assign new values to individual array elements.
        ChangeArrayElements(weekDays);
        // Display the array again to verify that it has changed.
        Console.WriteLine("Array weekDays after the call to ChangeArrayElements:");
        DisplayArray(weekDays);
    }
}
// The example displays the following output:
//         Sun Mon Tue Wed Thu Fri Sat
//
//        Array weekDays after the call to ChangeArray:
//        Sat Fri Thu Wed Tue Mon Sun
//
//        Array weekDays after the call to ChangeArrayElements:
//        Mon Wed Fri Wed Tue Mon Sun

Matrizes multidimensionais

As matrizes podem ter mais de uma dimensão. Por exemplo, as declarações a seguir criam quatro matrizes. Duas matrizes têm duas dimensões. Duas matrizes têm três dimensões. As duas primeiras declarações declaram o comprimento de cada dimensão, mas não inicializam os valores da matriz. As duas segundas declarações usam um inicializador para definir os valores de cada elemento na matriz multidimensional.

int[,] array2DDeclaration = new int[4, 2];

int[,,] array3DDeclaration = new int[4, 2, 3];

// Two-dimensional array.
int[,] array2DInitialization =  { { 1, 2 }, { 3, 4 }, { 5, 6 }, { 7, 8 } };
// Three-dimensional array.
int[,,] array3D = new int[,,] { { { 1, 2, 3 }, { 4,   5,  6 } },
                                { { 7, 8, 9 }, { 10, 11, 12 } } };

// Accessing array elements.
System.Console.WriteLine(array2DInitialization[0, 0]);
System.Console.WriteLine(array2DInitialization[0, 1]);
System.Console.WriteLine(array2DInitialization[1, 0]);
System.Console.WriteLine(array2DInitialization[1, 1]);

System.Console.WriteLine(array2DInitialization[3, 0]);
System.Console.WriteLine(array2DInitialization[3, 1]);
// Output:
// 1
// 2
// 3
// 4
// 7
// 8

System.Console.WriteLine(array3D[1, 0, 1]);
System.Console.WriteLine(array3D[1, 1, 2]);
// Output:
// 8
// 12

// Getting the total count of elements or the length of a given dimension.
var allLength = array3D.Length;
var total = 1;
for (int i = 0; i < array3D.Rank; i++)
{
    total *= array3D.GetLength(i);
}
System.Console.WriteLine($"{allLength} equals {total}");
// Output:
// 12 equals 12

Para matrizes multidimensionais, os elementos são percorridos de tal forma que os índices da dimensão mais à direita são incrementados primeiro, depois a próxima dimensão esquerda, e assim por diante, para o índice mais à esquerda. O exemplo a seguir enumera uma matriz 2D e 3D:

int[,] numbers2D = { { 9, 99 }, { 3, 33 }, { 5, 55 } };

foreach (int i in numbers2D)
{
    System.Console.Write($"{i} ");
}
// Output: 9 99 3 33 5 55

int[,,] array3D = new int[,,] { { { 1, 2, 3 }, { 4,   5,  6 } },
                        { { 7, 8, 9 }, { 10, 11, 12 } } };
foreach (int i in array3D)
{
    System.Console.Write($"{i} ");
}
// Output: 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12

Em uma matriz 2D, você pode pensar no índice esquerdo como a linha e no índice direito como a coluna.

No entanto, com matrizes multidimensionais, o uso de um loop for aninhado oferece mais controle sobre a ordem na qual processar os elementos da matriz:

int[,,] array3D = new int[,,] { { { 1, 2, 3 }, { 4,   5,  6 } },
                        { { 7, 8, 9 }, { 10, 11, 12 } } };

for (int i = 0; i < array3D.GetLength(0); i++)
{
    for (int j = 0; j < array3D.GetLength(1); j++)
    {
        for (int k = 0; k < array3D.GetLength(2); k++)
        {
            System.Console.Write($"{array3D[i, j, k]} ");
        }
        System.Console.WriteLine();
    }
    System.Console.WriteLine();
}
// Output (including blank lines): 
// 1 2 3
// 4 5 6
// 
// 7 8 9
// 10 11 12
//

Passar matrizes multidimensionais como argumentos

Você passa uma matriz multidimensional inicializada para um método da mesma forma que passa uma matriz unidimensional. O código a seguir mostra uma declaração parcial de um método de impressão que aceita uma matriz bidimensional como seu argumento. Você pode inicializar e passar uma nova matriz em uma etapa, como é mostrado no exemplo a seguir. No exemplo a seguir, uma matriz bidimensional de inteiros é inicializada e passada para o Print2DArray método. O método exibe os elementos da matriz.

static void Print2DArray(int[,] arr)
{
    // Display the array elements.
    for (int i = 0; i < arr.GetLength(0); i++)
    {
        for (int j = 0; j < arr.GetLength(1); j++)
        {
            System.Console.WriteLine("Element({0},{1})={2}", i, j, arr[i, j]);
        }
    }
}
static void ExampleUsage()
{
    // Pass the array as an argument.
    Print2DArray(new int[,] { { 1, 2 }, { 3, 4 }, { 5, 6 }, { 7, 8 } });
}
/* Output:
    Element(0,0)=1
    Element(0,1)=2
    Element(1,0)=3
    Element(1,1)=4
    Element(2,0)=5
    Element(2,1)=6
    Element(3,0)=7
    Element(3,1)=8
*/

Matrizes irregulares

Uma matriz irregular é uma matriz cujos elementos são matrizes, possivelmente de tamanhos diferentes. Uma matriz irregular às vezes é chamada de "matriz de matrizes". Seus elementos são tipos de referência e são inicializados em null. Os exemplos a seguir mostram como declarar, inicializar e acessar matrizes irregulares. O primeiro exemplo, jaggedArray, é declarado em uma instrução. Cada matriz contida é criada em instruções subsequentes. O segundo exemplo, jaggedArray2 é declarado e inicializado em uma instrução. É possível misturar matrizes irregulares e multidimensionais. O exemplo final, jaggedArray3, é uma declaração e inicialização de uma matriz irregular unidimensional que contém três elementos de matriz bidimensional de tamanhos diferentes.

int[][] jaggedArray = new int[3][];

jaggedArray[0] = [1, 3, 5, 7, 9];
jaggedArray[1] = [0, 2, 4, 6];
jaggedArray[2] = [11, 22];

int[][] jaggedArray2 = 
[
    [1, 3, 5, 7, 9],
    [0, 2, 4, 6],
    [11, 22]
];

// Assign 77 to the second element ([1]) of the first array ([0]):
jaggedArray2[0][1] = 77;

// Assign 88 to the second element ([1]) of the third array ([2]):
jaggedArray2[2][1] = 88;

int[][,] jaggedArray3 =
[
    new int[,] { {1,3}, {5,7} },
    new int[,] { {0,2}, {4,6}, {8,10} },
    new int[,] { {11,22}, {99,88}, {0,9} }
];

Console.Write("{0}", jaggedArray3[0][1, 0]);
Console.WriteLine(jaggedArray3.Length);

Os elementos de uma matriz irregular devem ser inicializados antes que você possa usá-los. Cada um dos elementos é em si uma matriz. Também é possível usar inicializadores para preencher os elementos da matriz com valores. Ao usar inicializadores, você não precisa do tamanho da matriz.

Este exemplo cria uma matriz cujos elementos são eles próprios matrizes. Cada um dos elementos da matriz tem um tamanho diferente.

// Declare the array of two elements.
int[][] arr = new int[2][];

// Initialize the elements.
arr[0] = [1, 3, 5, 7, 9];
arr[1] = [2, 4, 6, 8];

// Display the array elements.
for (int i = 0; i < arr.Length; i++)
{
    System.Console.Write("Element({0}): ", i);

    for (int j = 0; j < arr[i].Length; j++)
    {
        System.Console.Write("{0}{1}", arr[i][j], j == (arr[i].Length - 1) ? "" : " ");
    }
    System.Console.WriteLine();
}
/* Output:
    Element(0): 1 3 5 7 9
    Element(1): 2 4 6 8
*/

Matrizes digitadas implicitamente

Você pode criar uma matriz digitada implicitamente na qual o tipo da instância da matriz é inferido a partir dos elementos especificados no inicializador da matriz. As regras para qualquer variável digitada implicitamente também se aplicam a matrizes digitadas implicitamente. Para obter mais informações, consulte Variáveis locais digitadas implicitamente.

Os exemplos a seguir mostram como criar uma matriz digitada implicitamente:

int[] a = new[] { 1, 10, 100, 1000 }; // int[]

// Accessing array
Console.WriteLine("First element: " + a[0]);
Console.WriteLine("Second element: " + a[1]);
Console.WriteLine("Third element: " + a[2]);
Console.WriteLine("Fourth element: " + a[3]);
/* Outputs
First element: 1
Second element: 10
Third element: 100
Fourth element: 1000
*/

var b = new[] { "hello", null, "world" }; // string[]

// Accessing elements of an array using 'string.Join' method
Console.WriteLine(string.Join(" ", b));
/* Output
hello  world
*/

// single-dimension jagged array
int[][] c =
[
    [1,2,3,4],
    [5,6,7,8]
];
// Looping through the outer array
for (int k = 0; k < c.Length; k++)
{
    // Looping through each inner array
    for (int j = 0; j < c[k].Length; j++)
    {
        // Accessing each element and printing it to the console
        Console.WriteLine($"Element at c[{k}][{j}] is: {c[k][j]}");
    }
}
/* Outputs
Element at c[0][0] is: 1
Element at c[0][1] is: 2
Element at c[0][2] is: 3
Element at c[0][3] is: 4
Element at c[1][0] is: 5
Element at c[1][1] is: 6
Element at c[1][2] is: 7
Element at c[1][3] is: 8
*/

// jagged array of strings
string[][] d =
[
    ["Luca", "Mads", "Luke", "Dinesh"],
    ["Karen", "Suma", "Frances"]
];

// Looping through the outer array
int i = 0;
foreach (var subArray in d)
{
    // Looping through each inner array
    int j = 0;
    foreach (var element in subArray)
    {
        // Accessing each element and printing it to the console
        Console.WriteLine($"Element at d[{i}][{j}] is: {element}");
        j++;
    }
    i++;
}
/* Outputs
Element at d[0][0] is: Luca
Element at d[0][1] is: Mads
Element at d[0][2] is: Luke
Element at d[0][3] is: Dinesh
Element at d[1][0] is: Karen
Element at d[1][1] is: Suma
Element at d[1][2] is: Frances
*/

No exemplo anterior, observe que, com matrizes digitadas implicitamente, nenhum colchete é usado no lado esquerdo da instrução de inicialização. Além disso, matrizes irregulares são inicializadas usando new [] exatamente como matrizes unidimensionais.

Quando você cria um tipo anônimo que contém uma matriz, a matriz deve ser digitada implicitamente no inicializador de objeto do tipo. No exemplo a seguir, contacts é uma matriz implicitamente tipada de tipos anônimos, cada um dos quais contém uma matriz chamada PhoneNumbers. A var palavra-chave não é usada dentro dos inicializadores de objeto.

var contacts = new[]
{
    new
    {
        Name = "Eugene Zabokritski",
        PhoneNumbers = new[] { "206-555-0108", "425-555-0001" }
    },
    new
    {
        Name = "Hanying Feng",
        PhoneNumbers = new[] { "650-555-0199" }
    }
};