10
respostas

System.IndexOutOfRangeException

Olá a todos,

Já faz mesmo muito tempo que tenho tido vários erros e sempre que resolvo um, aparece outro. Li todos os comentários possíveis aqui e nao encontro resposta.

Agradeco a quem puder ajudar, pois nao estou entendo o porque de receber este erro pois o código está como o dos exercícios dados na aula.

An unhandled exception of type 'System.IndexOutOfRangeException' occurred in CaixaEletronico.exe

Additional information: O Index estava fora da area do Array(Arraybereich).

public void AdicionaConta(Conta conta)
{
    this.contas[this.quantidadeDeContas] = conta;//o erro está aqui
    this.quantidadeDeContas++;
    comboContas.Items.Add(conta.Titular.Nome);
}

Agradeco

10 respostas

Este erro acontece quando você tenta inserir um valor acima do limite máximo do array.

Qual o tamanho do array this.contas ? Verifique isto.

Provavelmente this.quantidadeDeContas está estorando o limite do array.

Lembre-se que o array inicia em 0 (primeira posição) e termina no tamanho_do_array-1,

Olá Gabriel, obrigado.

Na verdade nao sei como problema poderá ser no tamanho do array, pois já tentei com diferentes valores.

Se puder, dá uma olhada no código, obrigado.

public partial class Titular : Form
    {
        private Conta[] contas;
        private int quantidadeDeContas;
        public Titular()
        {
            InitializeComponent();
        }

        private void Titular_Load(object sender, EventArgs e)
        {
            this.contas = new ContaCorrente[30]; 

            this.contas[0] = new ContaCorrente();
            contas[0].Numero = 1; contas[0].Nome = "Conta Corrente";
            contas[0].Titular = new Cliente();
            contas[0].Titular.Nome = "Vitor";
            contas[0].Saldo = 100;

            contas[1] = new ContaPoupanca();
            contas[1].Numero = 2;
            contas[1].Titular = new Cliente();
            contas[1].Titular.Nome = "Mario"; contas[1].Nome = "Conta Poupanca";
            this.quantidadeDeContas =30;
            foreach (Conta conta in contas)
            {
                if (conta != null)
                    comboContas.Items.Add(conta.Titular.Nome);
            }
            comboContas.DisplayMember = "Titular";
        }

        private void comboContas_SelectedIndexChanged(object sender, EventArgs e)
        {
            string titularSelecionado = comboContas.Text; 

            int indiceSelecionado = comboContas.SelectedIndex;
            Conta contaSelecionada = contas[indiceSelecionado];
            txtTitular.Text = Convert.ToString(contaSelecionada.Nome);
            txtNumero.Text = Convert.ToString(contaSelecionada.Numero);
            txtSaldo.Text = Convert.ToString(contaSelecionada.Saldo);

        }

        private Conta BuscaContaSelecionada()
        {
            int indiceSelecionado = comboContas.SelectedIndex;
            return this.contas[indiceSelecionado];
        }
        private void btnSaca_Click(object sender, EventArgs e)
        {
            string txtValorSaque = txtValor.Text;
            Conta contaSelecionada = this.BuscaContaSelecionada();

            contaSelecionada.Saca(Convert.ToDouble(txtValor.Text));
        }

        private void btnDeposita_Click(object sender, EventArgs e)
        {
            string txtValorDoDeposito = txtValor.Text;
            Conta contaSelecionada = this.BuscaContaSelecionada();
            contaSelecionada.Deposita(Convert.ToDouble(txtValor.Text));
        }

        private void btnTransferir_Click(object sender, EventArgs e)
        {
            Conta conta1 = BuscaContaSelecionada();
            int indiceSelecionado = cmbDestinoDaTransferencia.SelectedIndex;
            Conta conta2 = this.contas[indiceSelecionado];

            conta1.Transfere(Convert.ToDouble(txtValor.Text), conta2);
            txtTitular.Text = conta2.Titular.Nome;
            txtNumero.Text = conta2.Numero.ToString();
            txtSaldo.Text = conta2.Saldo.ToString();
        }

        private void btnClean_Click(object sender, EventArgs e)
        {
            txtTitular.Clear();
            txtNumero.Clear();
            txtSaldo.Clear();
            txtValor.Clear();
        }

        private void cmbDestinoDaTransferencia_SelectedIndexChanged(object sender, EventArgs e)
        {
            int indiceSelecionado = cmbDestinoDaTransferencia.SelectedIndex;
            Conta contaSelecionada = this.contas[indiceSelecionado];

            txtTitular.Text = contaSelecionada.Titular.Nome;
            txtNumero.Text = contaSelecionada.Numero.ToString();
            txtSaldo.Text = contaSelecionada.Saldo.ToString();
        }

        public void AdicionaConta(Conta conta)
        {
            this.contas[this.quantidadeDeContas] = conta;
            this.quantidadeDeContas++;
            comboContas.Items.Add(conta); 
        }

        private void btnNovoCadastro_Click(object sender, EventArgs e)
        {
            CadastroDeConta cadastroDeContas = new CadastroDeConta(this);
            if (cadastroDeContas.ShowDialog() == DialogResult.OK            
            {
                Application.Run(new CadastroDeConta(this));            
            }
        }
    }

Vi o código, mas ainda não pude rodar aqui.

Na linha 15 tem o seguinte: this.contas = new ContaCorrente[30];

Na linha 27 tem: this.quantidadeDeContas = 30;

Então esta linha não é possível: this.contas[this.quantidadeDeContas] = conta;

Por que o maior índice que o this.contas suporta é 29.

O array vai de 0 a 29. Não pode ter um índice com valor 30.

Mas, vou tentar instalar o VS aqui para confirmar.

Obrigado Gabriel :) retirei a linha

this.quantidadeDeContas = 30;

mas o erro persiste

no erro aparece que a variavel Titular esta null :/

Graziela,

Você precisa adequar o código de exercícios anteriores:

Troque De:

this.contas[0] = new ContaCorrente();
contas[0].Numero = 1; contas[0].Nome = "Conta Corrente";
contas[0].Titular = new Cliente();
contas[0].Titular.Nome = "Vitor";
contas[0].Saldo = 100;

Para:

Conta c1 = new ContaCorrente();
c1.Numero = 1; contas[0].Nome = "Conta Corrente";
c1.Titular = new Cliente();
c1.Titular.Nome = "Vitor";
c1.Saldo = 100;
this.AdicionaConta(c1);

Adeque de forma similar a segunda conta criada e retire o ForEach, porque o ForEach irá percorrer de 0 a 29, mas nesse momento você criou apenas duas contas. As posições de 2 à 29 ainda estarão com NULL.

Além disso, já que foi criado o método AdicionaConta, não devemos mais manipular o array diretamente. Sempre que quiser criar uma nova conta, deixe que o método AdicionaConta faça isso.

//this.contas[this.quantidadeDeContas] = conta; 
//-- Só tratar para se adequar ao formato de contar de 0 em diante
this.contas[this.quantidadeDeContas-1] = conta;

Baixei os arquivos da própria aula anterior para fazer o exercício em cima e tive o mesmo erro: System.IndexOutOfRangeException: 'O índice estava fora dos limites da matriz.'

Resolvi da seguinte forma:

public void AdicionaConta(Conta conta)
 {
    contas = new Conta[this.quantidadeDeContas + 1];
    comboContas.Items.Add(conta.Titular.Nome);

    destinoDaTransferencia.Items.Add(conta);

    this.contas[this.quantidadeDeContas] = conta;
    this.quantidadeDeContas++;
}

Olá, pessoal!

Esse tópico é antigo! Graziela, conseguiu solucionar seu problema? Se sim, escolha qual resposta que deu a solução, por favor :)

Fábio, sua solução apesar de funcionar, tem um problema.

Toda vez que você adicionar uma conta, seu vetor será zerado. Ou seja, todas as outras contas que você tiver cadastrada, irão sumir.

O erro System.IndexOutOfRangeException: 'O índice estava fora dos limites da matriz.' significa que você está tentando adicionar uma conta num índice inválido.

Em termos práticos, seu vetor está cheio!

O código do curso está certo e foi feito de propósito. Tanto que há o exercício 5 do curso chamado Cadastro de Muitas contas que pede para fazer com que possam ser cadastrados um número ilimitado de contas.

A solução correta é aumentar o seu vetor para ter novos espaços para adicionar novas contas. Exemplo:

public void AdicionaConta (Conta conta)
{
    // Primeiro verifica se o vetor está cheio
    if(this.quantidadeDeContas == this.contas.Length)
    {
       // Se estiver cheio, criar um novo com mais espaços
        Conta[] novo = new Conta[this.contas.Length * 2];

        // Copia tudo que tem no vetor atual para esse novo
        for(int i = 0; i < this.quantidadeDeContas; i++)
        {
            novo[i] = this.contas[i];
        }

        // Substitui o vetor atual pelo novo
        this.contas = novo;
    }

    // Independente de termos aumentado ou não o vetor
    // Sempre haverá espaços disponíveis para novas contas
    this.contas[this.quantidadeDeContas] = conta;
    this.quantidadeDeContas++;
    comboContas.Items.Add(conta);
}

Entendeu?

Arthur, na pratica não gerou esse problema. No meu código ele já gerava 3 contas e todas que eu adicionei foram acrescentadas na lista.

Me pareceu que o System.IndexOutOfRangeException ocorreu devido a criação de um array com 0 posições, por isso eu coloquei "+1" para não ocorrer este caso e, após isso, funcionou.

Segue o meu código completo de Form1.cs:

using Caelum.CaixaEletronico.Modelo;
using Caelum.CaixaEletronico.Modelo.Contas;
using Caelum.CaixaEletronico.Modelo.Usuarios;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace CaixaEletronico
{
    public partial class Form1 : Form
    {
        private Conta [] contas;
        private int quantidadeDeContas;

        public Form1()
        {
            InitializeComponent();
        }

        private void Form1_Load(object sender, EventArgs e)
        {

            contas = new Conta[3];

            Conta contaDoVictor = new ContaCorrente();
            contaDoVictor.Titular = new Cliente();
            contaDoVictor.Titular.Nome = "Victor";
            contaDoVictor.Numero = 1;
            contas[0] = contaDoVictor;

            Conta contaDoGuilherme = new ContaPoupanca();
            contaDoGuilherme.Titular = new Cliente();
            contaDoGuilherme.Titular.Nome = "Guilherme";
            contaDoGuilherme.Numero = 2;
            contas[1] = contaDoGuilherme;

            Conta contaDoMauricio = new ContaInvestimento();
            contaDoMauricio.Titular = new Cliente();
            contaDoMauricio.Titular.Nome = "Mauricio";
            contaDoMauricio.Numero = 3;
            contas[2] = contaDoMauricio;

            foreach (Conta conta in this.contas)
            {
                comboContas.Items.Add(conta.Titular.Nome);
                destinoDaTransferencia.Items.Add(conta);
                this.contas[this.quantidadeDeContas] = conta;
                this.quantidadeDeContas++;
            }
        }

        private void button1_Click(object sender, EventArgs e)
        {
            string textoValorSaque = valorOperacao.Text;

            double valorDeposito = Convert.ToDouble(textoValorSaque);

            int indiceSelecionado = comboContas.SelectedIndex;

            Conta contaSelecionada = this.contas[indiceSelecionado];
            contaSelecionada.Deposita(valorDeposito);

            this.MostraConta(contaSelecionada);
        }

        private void button2_Click(object sender, EventArgs eA)
        {
            string textoValorSaque = valorOperacao.Text;

            double valorSaque = Convert.ToDouble(textoValorSaque);
            Conta contaSelecionada = this.BuscaContaSelecionada();

            try { 
                contaSelecionada.Saca(valorSaque);
                MessageBox.Show("Dinheiro Liberado");
            }
            catch (SaldoInsuficienteException e)
            {
                MessageBox.Show("Saldo insuficiente. " + e.Message);
            }
            catch (ArgumentException e)
            {
                MessageBox.Show("Não é possível sacar um valor negativo. " + e.Message);
            }

            this.MostraConta(contaSelecionada);
        }

        private void MostraConta(Conta conta)
        {
            textoTitular.Text = conta.Titular.Nome;
            textoSaldo.Text = Convert.ToString(conta.Saldo);
            textoNumero.Text = Convert.ToString(conta.Numero);
        }

        private Conta BuscaContaSelecionada()
        {
            int indiceSelecionado = comboContas.SelectedIndex;
            return this.contas[indiceSelecionado];
        }


        private void comboBox1_SelectedIndexChanged(object sender, EventArgs e)
        {
            string titularSelecionado = comboContas.Text;
            Conta contaSelecionada = this.BuscaContaSelecionada();
            this.MostraConta(contaSelecionada);
        }

        private void button4_Click(object sender, EventArgs e)
        {
            Conta contaSelecionada = this.BuscaContaSelecionada();

            int indiceDaContaDestino = destinoDaTransferencia.SelectedIndex;

            Conta contaDestino = this.contas[indiceDaContaDestino];

            string textoValor = valorOperacao.Text;
            double valorTransferencia = Convert.ToDouble(textoValor);

            contaSelecionada.TransferePara(contaDestino, valorTransferencia);

            this.MostraConta(contaSelecionada);

        }

        public void AdicionaConta(Conta conta)
        {
            contas = new Conta[this.quantidadeDeContas + 1];
            comboContas.Items.Add(conta.Titular.Nome);

            destinoDaTransferencia.Items.Add(conta);

            this.contas[this.quantidadeDeContas] = conta;
            this.quantidadeDeContas++;
        }

        private void button3_Click(object sender, EventArgs e)
        {
            CadastroDeContas cadastro = new CadastroDeContas(this);
            cadastro.ShowDialog();
        }
    }
}

Olá, Fábio!

O System.IndexOutOfRangeException ocorreu exatamente pelo que eu disse. Seu vetor foi criado com tamanho 3 e você criou e adicionou 3 contas ao vetor, deixando ele cheio e a variável quantidadeDeContas com valor 3.

Ao usar o código da aula sem modificá-lo, ele vai tentar inserir na posição 3 atual valor da variável quantidadeDeContas. Só que não existe a posição 3 no vetor.

O problema do seu código é que, toda vez que você chamar o método AdicionaConta ele vai criar um novo vetor e você vai perder as três contas que tinha anteriormente nele, ficando somente a nova conta adicionada.

As contas vão continuar existindo na comboContas, pois são referências separadas.

Tente executar seu código novamente. Adicione uma quarta conta e depois tente fazer depósitos e saques com todas as contas da combo. Ocorrerá um erro.