Solucionado (ver solução)
Solucionado
(ver solução)
8
respostas

Sobre o código rodando "globalmente" mesmo estando dentro de uma variável

Sinto que isso tem haver com os endereços de memória né?

O código desse exercício foi esse:

            ContaCorrente contaBruno = new ContaCorrente();
            contaBruno.titular = "Bruno";
            contaBruno.Depositar(500);
            Console.WriteLine("Conta Bruno: " + contaBruno.saldo);

            ContaCorrente contaGabriela = new ContaCorrente();
            contaGabriela.titular = "Gabriela";

            bool resultadoTransferencia = contaBruno.Transferir(77, contaGabriela);
            Console.WriteLine("Conta Bruno: " + contaBruno.saldo);
            Console.WriteLine("Conta Gabriela: " + contaGabriela.saldo);

Minha dúvida é sobre esse trecho:

            bool resultadoTransferencia = contaBruno.Transferir(77, contaGabriela);

Aqui foi criado uma variável chamada "resultadoTransferencia" que aparentemente deveria apenas dizer se algo é true ou false (por ser um bool), mas em nenhum momento estaria explicitamente mandando rodar aquelas funções ali dentro e alterar valores.

contaBruno.Transferir(77, contaGabriela);

Ok aqui me parece que esta explicitamente mandando o compilador rodar essa função "Transferir" quando ler essa linha, mas no outro caso ali era só uma variável guardando informação.

Pelo que estou percebendo quando se mexe com objeto não pode nem guardar algo dentro de uma variável/função para usar depois, a partir do momento que o compilador ler aquilo ele já vai aplicar as alterações e já era?

Fiz uma variável de teste aqui na intenção de "zerar a conta pra fazer outros testes" que foi essa aqui:

            double assalto = (contaBruno.saldo = 0);
            Console.WriteLine("Conta Bruno: " + contaBruno.saldo);

            contaBruno.saldo = assalto;
            Console.WriteLine("Conta Bruno: " + contaBruno.saldo);

Mas antes mesmo se explicitamente mandar rodar ali na segunda parte ele já tinha zerado a conta e deu 2 zero seguidos.

Eu não posso simplesmente guardar informação dentro de uma variável para usar só quando eu quiser?

8 respostas

Alves, bom dia.

Vamos analisar esse trecho de código:

bool resultadoTransferencia = contaBruno.Transferir(77, contaGabriela);

Primeiramente vamos pensar nessa linha como se estivéssemos lendo em voz alta. Então, temos uma variável do tipo booleana nomeada de 'resultadoTransferencia', essa variável recebe o resultado do método Transferir da ContaBancaria. O método Transferir vai tirar o dinheiro da contaBruno e depositar na contaGabriela, se tudo ocorrer certinho ele vai retornar verdadeiro, se algo der errado vai retornar falso. Esse retorno é armazenado na variavel resultadoTransferencia.

Aqui vemos que o método Tranferir foi executado e o retorno guardado na variável resultadoTransferencia, que pode ser usada para, por exemplo, exibir uma mensagem de erro ou sucesso ao usuário. Exemplo:

if (resultadoTransferencia == true)
{
    Console.WriteLine("Transferência executada com sucesso!");
}
else
{
    Console.WriteLine("Algo deu errado, por favor tente novamente.");
}

Caso você quisesse apenas guardar um booleano, deveria atribuir com um valor essa variável. Por exemplo:

bool resultadoTransferencia = true;

Agora vamos ver seu teste:

double assalto = (contaBruno.saldo = 0);
Console.WriteLine("Conta Bruno: " + contaBruno.saldo);

contaBruno.saldo = assalto;
Console.WriteLine("Conta Bruno: " + contaBruno.saldo);

Focando apenas na primeira linha:

double assalto = (contaBruno.saldo = 0);

Nessa linha temos duas coisas acontecendo:

  1. O saldo da contaBruno está sendo atribuido com o valor 0 (contaBruno.saldo = 0);

  2. O saldo da contaBruno está sendo atribuido na variável do tipo double 'assalto';

** Dica: quando for ler atribuições, veja tudo que está escrito depois do sinal de igual, nesse caso ''(contaBruno.saldo = 0);'' pois essa ação será a primeira a ser executada.

Acredito que aqui seja o problema, pelo que entendi, você queria que essa sua variável assalto sempre tivesse o valor 0, para poder zerar algum saldo sempre que precisasse. O código ficaria alo do tipo:

double assalto = 0; //definimos que a variavel assalto tem o valor 0
Console.WriteLine("Conta Bruno: " + contaBruno.saldo); //escrevemos  na tela o valor atual da conta do bruno;

contaBruno.saldo = assalto; // Aqui dizemos que o saldo da conta do bruno é igual ao valor da varivel assalto, ou seja, 0.
Console.WriteLine("Conta Bruno: " + contaBruno.saldo);// resultado exibido na tela é 0

Espero ter tirado sua dúvida.

Dica final:

Percebeu que essa sua variável assalto, criada para zerar uma conta, denota uma ação? Um assalto é uma ação certo? Na orientação a objetos ações são métodos, por isso deixo aqui o desafio de criar uma classe chamada Ladrão e com o método AssaltarContaBancária(), esse método vai zerar a conta do bruno, belê?

Bom dia Carla!

"pelo que entendi, você queria que essa sua variável assalto sempre tivesse o valor 0, para poder zerar algum saldo sempre que precisasse."

O objetivo dessa variável foi para deixar explicito esse comportamento que mencionei. Apenas atribuir o valor dela para 0 resolveria mas minha dúvida é sobre o comportamento e não sobre como chegar no resultado 0.

O que me deixou em dúvida aqui é que o valor do objeto foi alterado antes que eu mandasse ele ser alterado.

Essa variável chega no valor 0 tranquilamente (existe nenhuma dúvida sobre como fazer isso), mas ela zera a conta quando eu declaro a variável. Como eu disse ali em cima o código printa o valor 0 duas vezes: A 1º quando declarei e a 2º quando eu usei a variável.

solução!

Ok, agora entendi melhor sua dúvida, vamos lá.

O que me deixou em dúvida aqui é que o valor do objeto foi alterado antes que eu mandasse ele ser alterado.

Na verdade, você mandou o valor ser alterado, vamos analisar a declaração da variável assalto:

double assalto = (contaBruno.saldo = 0);

Essa linha, como disse anteriormente, faz duas ações, para melhor visualização vou dividir essas ações, uma em cada linha;

contaBruno.saldo = 0;
double assaldo = contaBruno.saldo;

Primeiro você atribuiu o saldo do bruno como 0. Nesse ponto o saldo do bruno já foi zerado;

Depois você atribuiu a variável assalto com o valor com o saldo da conta do bruno, que é zero;

É dessa forma que o compilador lê seu código:

contaBruno.saldo = 0;
double assaldo = contaBruno.saldo;
Console.WriteLine("Conta Bruno: " + contaBruno.saldo); //mostra 0 na tela

contaBruno.saldo = assalto;
Console.WriteLine("Conta Bruno: " + contaBruno.saldo);//mostra 0 na tela

Para que o programa tenha o resultado esperado, a declaração da variavel assalto ficaria dessa forma:

double assalto = 0;

Ou apenas ( já que o valor padrão de um double é 0)

double assalto;

Quando queremos deixar um comportamento explicito, no caso, queremos que o assalto apenas zere o valor do saldo (e não de qualquer outra variável), criamos um método para essa ação. Algo do tipo:

public void Assalto(ContaCorrente conta)
{
    conta.saldo = 0;
}

Comecei a fazer alguns testes aqui e me parece que é algo sobre a lógica de programação e não sobre o C# em si, escrevi esse código em C++ e houve o mesmo comportamento.

#include <iostream>
using namespace std;

int main() {
    int exemplo = 10;
    cout << exemplo << endl;

    int alterar = (exemplo *= 2);
    cout << exemplo << endl;

    exemplo += alterar;
    cout << exemplo << endl;
}

Ao declarar a variável "alterar" o valor guardado na variável "exemplo" já foi alterado.

É como se a variável em si tivesse se transformado em uma função ou algo do tipo.

#include <iostream>
using namespace std;

int exemplo = 10;
int alterar = (exemplo *= 2);


int main() {

    cout << exemplo << endl;
    exemplo += alterar;
    cout << exemplo << endl;
}

Mesmo usando variáveis globais o resultado é o mesmo, o valor original deixou de existir a partir do momento que disse em outra variável que o valor dela envolvia transformar o valor de outra variável.

Nesse caso achei até mais curioso pois achava que removendo de dentro da main o primeiro print teria o valor original.

Na verdade ainda não entendi 100% o caso mas acho que é melhor seguir em frente hahahaha

Fiz um segundo teste:


using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace _04_ByteBank
{
    class Program
    {
        static void Main(string[] args)
        {
            ContaCorrente contaBruno = new ContaCorrente();
            contaBruno.titular = "Bruno";

            Console.WriteLine("Conta Bruno: " + contaBruno.saldo);

            bool resultadoSaque = contaBruno.Sacar(300);
            Console.WriteLine("Conta Bruno: " + contaBruno.saldo);
            Console.WriteLine(resultadoSaque);

            contaBruno.Depositar(500);
            Console.WriteLine("Conta Bruno: " + contaBruno.saldo);

            ContaCorrente contaGabriela = new ContaCorrente();
            contaGabriela.titular = "Gabriela";

            bool resultadoTransferencia = contaBruno.Transferir(77, contaGabriela);
            Console.WriteLine("Conta Bruno: " + contaBruno.saldo);
            Console.WriteLine("Conta Gabriela: " + contaGabriela.saldo);

            double assalto = (contaBruno.saldo = 0);
            Console.WriteLine("Conta Bruno: " + contaBruno.saldo);

            contaBruno.saldo = assalto;
            Console.WriteLine("Conta Bruno: " + contaBruno.saldo);









            Console.WriteLine("===========================");
            contaBruno.saldo += 500;
            Console.WriteLine("Conta Bruno: " + contaBruno.saldo);
            Console.WriteLine(assalto);
            Console.WriteLine("Conta Bruno: " + contaBruno.saldo);

            Console.ReadLine();
        }
    }
}

O que interessa é só aquele pedaço no final abaixo do tracejado.

Aqui pelo menos o valor da contaBruno não foi alterado só pq toquei nessa variável 'assalto', printou 500, depois 0 e depois 500 denovo. Acredito que esse zero é o valor da própria variável "assalto" sem considerar nada mais.

Acho que a moral da história é: Fazer algo que parece uma mistura de variável com função é uma abominação e vai destruir tudo que encontrar pelo caminho.

Sim, é a lógica usada mesmo.

O comportamento vai se repetir em qualquer linguagem e não tem relação entre ser um variável local ou não.

É como se a variável em si tivesse se transformado em uma função ou algo do tipo.

Variáveis não guardam comportamento (exceto no javascript**), apenas valores, então se você passar uma instrução após o sinal de = na hora de atribuir uma variável, o compilador vai resolver tudo primeiro, pegar o resultado e jogar na variável. Vamos a um exemplo:

int a = 5;
int b = 5;
int resultado  = a + b; //10

No exemplo acima, a única responsabilidade da variável resultado é guardar algum valor, o compilar executa a conta a+b, mas a resultado não sabe de onde ou de que forma esse valor foi atribuído a ela.

Voltando ao seu código:

double assalto = (contaBruno.saldo = 0);

Assalto é uma variável, então o compilador vai resolver tudo que estiver escrito após sinal de =, quando finalizar ele vai guardar o valor na variável assalto. Por isso o programa não está tendo o comportamento esperado.

** No javascript podemos colocar comportamento (funções) em variáveis , se tiver curiosidade de uma lida aqui.

No fim uma variável assim acaba virando uma "função de pobre" que funciona só uma vez e quebra depois.

Só não entendi muito bem a utilidade de algo assim, acabei usando pois o instrutor fez isso no exercício mas até agora não vejo algo positivo nessa forma de construir o código.