AnswerBun.com

Verificar dados antes de usar como elemento de array

Stack Overflow em Português Asked on January 4, 2022

No chat foi perguntado algo sobre validação de entrada de dados para evitar erro de pegar fora da faixa permitida. Achei a pergunta interessante e pena que não foi postada aqui, estou postando:

public static T[] ReplaceRange<T>(this T[]input, T[] replacement, int start) {
    for (int i = start; i < input.Length; i++) {
        T replacementItem = replacement[i - start];
        input[i] = replacementItem;
    }
    return input;
}

Como evitar o erro?

One Answer

Pontos de interesse:

  • Contratos
  • Erros de programação são resolvidos consertando-os
  • Algumas reorganizações
  • Existe coisa pronta que funciona melhor

Existem algumas formas, eu tenho gostado de usar contratos. Ele tem algumas desvantagens, mas em geral ajuda e deveria ser usado mais, o .NET usa o tempo todo em seus códigos. Se não gostar dele é só mudar para um if e lançar uma exceção (é o mesmo que o Requires() faz internamente na maioria dos casos, mas tem alguns que ele poderá ser retirado da execução, veja abaixo). Muda alguma coisa? Não muito, apenas que o erro é mais específico, e isso tem implicações positivas, mas pode mudar algo importante.

Uma outra possibilidade é usar um Assert() que pode ser garantidamente desligado, o que pode ser uma boa, afinal o erro Out of Bounds é erro de programação e a única solução possível é consertar o erro, a única coisa que podemos fazer é garantir que um código bem testado dê o erro em tempo de desenvolvimento e se tiver algum erro na chamada também tenha o problema resolvido. Se tiver certeza que o erro não acontece mais o Assert() não vai para produção, já o Requires() pode ir, mas ao mesmo tempo pode ser mais seguro se não tiver tanta certeza assim.

Na versão atual do Visual Studio essa retirada do Requires() não é automática, precisa instalar e configurar o uso de análise e retirada automática dos contratos.

Outra possibilidade é fazer nada, afinal erro de programação se resolve e não tenta contornar, e eu tenho optado por isso. Mas pode fazer algo assim:

Os nomes dos parâmetros do exemplo não são bons, são enganosos.

using static System.Console;
using static System.Diagnostics.Contracts.Contract;

public class Program {
    public static void Main() {
        foreach (var item in ReplaceRange(new int[] {0, 1, 2, 3, 4}, new int[] {5, 6, 7, 8, 9}, 2)) WriteLine(item);
    }
    public static T[] ReplaceRange<T>(T[] source, T[] destination, int start) {
        Requires(start >= 0, "O índice de início não pode ser menor que zero");
        Requires(start < source.Length, "O índice de início não pode ser maior que o fim do array");
        Requires(destination.Length >= source.Length - start, "O índice de início não pode ser maior que o que cabe");
        for (int i = start, j = 0; i < source.Length; i++, j++) destination[i] = source[j];
        return destination;
    }
}

Veja funcionando no ideone. E no .NET Fiddle. Também coloquei no GitHub para referência futura.

Não vou colocar para rodar online porque esses ambientes são limitados, a grande vantagem é quando a ferramenta ajuda, o Visual Studio por exemplo pode informar de problemas durante o desenvolvimento, ou tem ferramentas que geram testes para você baseado no contrato encontrado dentro do método (preciso até me atualizar porque mudou desde a última vez que usei).

Mas pode simplificar isso e usar o Array.Copy() que já existe no .NET. Se quiser só faça um wrap simples para considerar apenas o início da fonte e ele preencher sozinho o início do destino e o tamanho da cópia.

Postei mais com intuito de mostrar que tem alternativas, algumas que poucos conhecem, tem maneiras de resolver sem fazer nada no código e há maneiras de usar o que já tem pronto que será bem mais rápido porque fará uma cópia blittable, até onde dá.

Answered by Maniero on January 4, 2022

Add your own answers!

Related Questions

A conta matematica ta dando errado?? C#

1  Asked on December 16, 2021 by zehous

 

Qual utilidade de declarar uma coluna como Char(0)?

1  Asked on December 16, 2021 by user60252

   

Repetir campos de acordo com o numero do dropdown

3  Asked on December 16, 2021 by fabio-henrique

   

Vue router – problema com links dinamicos

0  Asked on December 16, 2021 by gabriel-porcher

       

Existe algo que compare o tipo do objeto?

1  Asked on December 16, 2021 by qattus

     

Angular múltiplos ngif else passando parametro no template

1  Asked on December 14, 2021 by herick

 

Condição de saída no do-while em código C

1  Asked on December 14, 2021 by steeph

       

Para que serve esse ‘in’ em C#?

1  Asked on December 14, 2021 by cypherpotato

     

Sobrecarga de método é polimorfismo?

1  Asked on December 14, 2021 by douglas-da-dias-silva

       

Não estou conseguindo cadastrar o nome de uma pessoas na minha agenda

2  Asked on December 14, 2021 by rafael-marques

     

Ask a Question

Get help from others!

© 2023 AnswerBun.com. All rights reserved. Sites we Love: PCI Database, MenuIva, UKBizDB, Menu Kuliner, Sharing RPP, SolveDir