none
ByRef e ByVal quando usar RRS feed

  • Discussão Geral

  • Li que certos tipos é aconselhável que sejam passados por referência pois tem uma melhor performance. Mesmo principio de C++

    Mas na prática quais são esse tipos?

    Por exemplo eu tenho optador por usar ByRef para objetos próprios (minhas classes), Listas List(Of..), e Date. Está certo essa minha escolha? Algum à acrescentar ou retirar?


    • Editado Matheus S. Silva quarta-feira, 13 de abril de 2016 21:00
    • Tipo Alterado Marcos SJ quinta-feira, 14 de abril de 2016 10:52
    quarta-feira, 13 de abril de 2016 20:59

Todas as Respostas

  • Bom dia Matheus S. Silva,

    Quanto as suas características:

    ByRef

    Especifica que um argumento é passado de tal forma que o procedimento chamado pode alterar o valor de uma variável subjacente ao argumento no código de chamada.

    ByVal

    Especifica que um argumento é passado de tal forma que o procedimento ou propriedade chamado não pode alterar o valor de uma variável subjacente ao argumento no código de chamada.

    Mas para entender melhor entender quando usar cada um peço que examine as informações contidas nos seguintes links:

    Entendendo Passagem por Valor e por Referência (Byval/ByRef)

    Passing Variables By Reference And By Value

    ByVal Vs. ByRef

    Espero ter ajudado.

    Atenciosamente


    Marcos SJ

    Esse conteúdo e fornecido sem garantias de qualquer tipo, seja expressa ou implícita

    MSDN Community Support

    Por favor, lembre-se de Marcar como Resposta as postagens que resolveram o seu problema. Essa é uma maneira comum de reconhecer aqueles que o ajudaram e fazer com que seja mais fácil para os outros visitantes encontrarem a resolução mais tarde.


    • Editado Marcos SJ quinta-feira, 14 de abril de 2016 11:07
    quinta-feira, 14 de abril de 2016 11:05
  • Matheus, primeiro veja tudo o que o Marcos postou - são links sobre o assunto e é bom para você entender melhor.

    De uma forma "resumida", ao você passar um argumento ByVal para um método, o método tem o VALOR da variável; basicamente é como se você fizesse isso:

    int ABC = 1;
    int CDE = ABC;

    Você entregou ao argumento do método o valor da variável passada. Dessa forma, se a variável for uma STRUCT, toda e qualquer alteração feita nela, pelo método, não será passado para a variável original. Veja:

    public class Test
    {
        int Abc = 1;
    
        public void Method(int Cde)
        {
            Cde++;
        }
    
        public void Run()
        {
            this.Method(this.Abc);
            //Abc continua 1, porque o método adicionou 1 no Cde
            //mas o Cde não tem vínculo com Abc
        }
    }

    Então neste caso você PRECISA usar ByRef, se você for usar este método ele deveria ser Ref, para retornar o valor alterado.

    Uma classe no entanto, pode ser ByVal, porque o VALOR da classe não é o conteúdo da classe, apenas a referência ao endereço onde ela está na memória. Por isso, se você tem uma classe ela ocupa um espaço na memória e a variável a qual ela está associada não guarda os bytes da classe, mas sim um endereço de 64bit aonde a classe (e suas variaveis, métodos etc) está guardada. Quando você atualiza uma propriedade (ou variável) da classe, a referencia permanece a mesma. Algo assim:

    public class Filho
    {
        string Nome;
        public Filho() { }
        public Filho(string Nome) { this.Nome = Nome; }
    }
    
    public class Test
    {
        Filho Abc = new Filho("Eu");
        //neste momento, foi alocado na memória um espaço para
        //o conteúdo da classe filho. Esse espaço tem um endereço
        //o valor contido em Abc não é "Eu" mas 0x000001231411
        //(exemplo), onde a classe está.
    
        public void Method(Filho Cde)
        {
            Cde.Nome += " Não";
        }
    
        public void Run()
        {
            this.Method(this.Abc);
            //Abc continua 0x000001231411
            //mas Abc.Nome mudou, pois Cde e Abc eram ambos
            //ponteiros para o mesmo endereço de memória que
            //armazena a instância de Filho() criada em Abc
        }
    }

    Espero não ter confundido mais ... rsrsrs

    EDIÇÃO

    Complementando. Seguindo este exemplo, se você fizer:

    public void Method(Filho Cde)
    {
        Cde = new Filho("Outro");
    }

    A variável "Abc" vai continuar sendo "Filho(Eu)". Porque você trocou o valor (referência) de Cde para uma nova instância, mas "Abc" continua vinculada. No entanto, se o método fosse ByRef:

    public void Method(ref Filho Cde)
    {
        Cde = new Filho("Outro");
    }

    Então "Abc" passaria a ser "Filho(Outro)" ao invés de "Filho(Eu)". Porque com REF, você alterou o valor de "Cde", vinculado a "Abc". O valor DA CLASSE (o endereço 0x000001231411) onde ela está.

    • Editado SammuelMiranda quinta-feira, 14 de abril de 2016 12:06 Complemento
    quinta-feira, 14 de abril de 2016 11:50
  • Eu conheço as questões que envolvem alocação de memória e variáveis por referência e valor. Programei muito em C/C++ no passado. E até onde sei, quando uma variável é passada por valor o conteúdo dela é copiado pela função, ou seja o conteúdo é duplicado, e dependendo do tamanho do seu objeto isso pode ser dispendioso do ponto de vista de performance.
    A a biblioteca MSDN aconselha ByRef para tais elementos.

    https://msdn.microsoft.com/en-us/library/ddck1z30.aspx#Anchor_1

    https://msdn.microsoft.com/pt-br/library/ddck1z30.aspx#Anchor_1

    O motivo do meu tópico é mais para tratar de performance e não do conceito.

    quinta-feira, 14 de abril de 2016 12:55