Property defined in constructor only returns zero value

Asked

Viewed 120 times

2

I created a Web API in C# that returns me a list of products in JSON. However, the property PrecoVenda is always returned with the value zero and I noticed that this occurs because in the class constructor Produto, the PrecoCusto also remains at zero while running the program, as you can see in the image below.

PrecoCusto = 0

  • If I have the values defined in ListaProdutos.cs (on the estates PrecoCusto), the value should not be captured in the code above?

  • How this could be solved?

Follows the code:

Productoscontroller.Cs:

using System.Collections.Generic;
using System.Web.Http;
using WebAPI_0527.Models;
using WebAPI_0527.Dados;

namespace WebAPI_0527.Controllers
{
    public class ProdutosController : ApiController
    {
        [HttpGet]
        public List<Produto> GetProdutos()
        {
            return ListaProdutos.GetList();
        }
    }
}

Listproducts.Cs

using System.Collections.Generic;
using WebAPI_0527.Models;

namespace WebAPI_0527.Dados
{
    public class ListaProdutos
    {
        public static List<Produto> GetList()
        {
            List<Produto> listaProdutos = new List<Produto>()
            {
                new Produto() { Id = 1, Nome = "Arroz", PrecoCusto = 12, Unidade = Produto.TipoDeUnidade.Kg.ToString(), Quantidade = 9 },
                new Produto() { Id = 2, Nome = "Leite", PrecoCusto = 5, Unidade = Produto.TipoDeUnidade.Litro.ToString(), Quantidade = 6 }
            };

            return listaProdutos;
        }
    }
}

Product.Cs

namespace WebAPI_0527.Models
{
    public class Produto
    {
        public int Id { get; set; }
        public string Nome { get; set; }
        public string Unidade { get; set; }
        public double Quantidade { get; set; }
        public double PrecoCusto { get; set; }
        public double PrecoVenda { get; set; }

        public Produto()
        {
            PrecoVenda = PrecoCusto + PrecoCusto / 3;
        }

        public enum TipoDeUnidade
        {
            Unidade,
            Litro,
            Balde,
            Par,
            Kg
        }
    }
}
  • How will you define one die that depends on another if I another has not been defined?

3 answers

4


There are two ways to solve this. The first is to work. It’s a little detail that’s wrong. The second, and this is the one I’m going to show, is learning how to really solve this problem. I would sort of solve it like this (there’s ways to improve more:

using static System.Console;
using System.Collections.Generic;

public class Program {
    public static void Main() {
        var listaProdutos = ListaProdutos.GetList();
        foreach (var produto in listaProdutos) WriteLine($"{produto.Nome} -> {produto.PrecoVenda:C}");
    }
}

public class ListaProdutos {
    public static List<Produto> GetList() => new List<Produto>() {
            new Produto(id : 1, nome : "Arroz", precoCusto : 12, unidade : Produto.TipoDeUnidade.Kg, quantidade : 9),
            new Produto(2, "Leite", Produto.TipoDeUnidade.Litro, 5, 6)
        };
}

public class Produto {
    public int Id { get; }
    public string Nome { get; set; }
    public TipoDeUnidade Unidade { get; set; }
    public decimal Quantidade { get; }
    public decimal PrecoCusto { get; set; }
    public decimal PrecoVenda { get => PrecoCusto * (4M / 3M); }
    
    public Produto(int id, string nome, TipoDeUnidade unidade, decimal quantidade, decimal precoCusto) {
        Id = id;
        Nome = nome;
        Unidade = unidade;
        Quantidade = quantidade;
        PrecoCusto = precoCusto;
    }
    
    public enum TipoDeUnidade { Unidade, Litro, Balde, Par, Kg }
}

Behold working in the ideone. And in the repl it.. Also put on the Github for future reference.

Some mistakes:

  • An object must be constructed in valid state, in most cases one should not have a constructor default, without parameters, you must have a constructor that receives all the minimum data for the object to be in valid state. See What good is a builder?. That’s what I did.
  • The Id used to be an immutable property, so there’s no point in having a set.
  • I let the name and the unit change, but I have doubts whether it should, this is the problem of artificial examples or no clear definition.
  • To Unidade shouldn’t be string It’s the type of the enumeration itself. Even if you need this to put in a database or visually present it, you should have other ways of doing it. For the database it would be better to make one cast in the enumeration itself and have a property to pick up the unit name when you need the name or pick up the enumeration item and apply the ToString() when you need.
  • When we work with monetary values what we want accuracy the correct type is the decimal and not the double that has rounding problems.
  • The estate PrecoDeVenda It seems to me that it’s what we call virtual, which is that it always takes another value and returns, so it doesn’t have to have been. If you need to have a state, because it should not always be changed according to the cost or it can have a custom value, then you need to think of another logic. I can’t say anything because I don’t know the real need.
  • I took the opportunity to make the code more modern, readable in my conception, and using mathematics more optimally and intelligently.
  • Note that the amount is unchangeable, because I don’t think it should be changed directly. In fact it is common in object orientation not to have properties being directly modified. It is more common to have a method that performs a specific operation that has the side effect of changing internal state. There are cases where the change of ownership is appropriate, but in this case I think a method that establishes a sale or purchase or other entry and exit operation that should be used, maybe it should not even be in the manufacturer, or it should be in a different way.

2

If I have the values defined in the List products.Cs (in the Precocusto properties), the value should not be captured in the code above?

The answer is no through your code:

new Produto() { 
    Id = 1, 
    Nome = "Arroz", 
    PrecoCusto = 12, 
    Unidade = Produto.TipoDeUnidade.Kg.ToString(), 
    Quantidade = 9 
}

because first, the class is instantiated Produto and when you pass the constructor the property is still its default value which is 0 and when you enter the keys you start passing values to that instance of the class Produto.

This is important to know, that first there is the creation of the instance and then the passage of value, of course it can be created a constructor with paraments and do the calculation in the constructor, but, I find more logical when the value is a calculation to be done as in the example below:

How this could be solved?

How the value is calculated can be placed directly in the class as follows:

public class Produto
{
    public int Id { get; set; }
    public string Nome { get; set; }
    public string Unidade { get; set; }
    public double Quantidade { get; set; }
    public double PrecoCusto { get; set; }      
    public double PrecoVenda
    {
        get 
        {
            return (PrecoCusto + PrecoCusto) / 3;
        }
    }

    public Produto()
    {       
    }

    public enum TipoDeUnidade
    {
        Unidade,
        Litro,
        Balde,
        Par,
        Kg
    }
}

Check in the Online example

  • 1

    Great explanation, friend! Thank you very much!

1

In addition to the way @Virgilionovic demonstrated, there is another: the passing of the cost price per constructor with parameter,

public Produto(double precoCusto)
{
    PrecoCusto = precoCusto;
    PrecoVenda = PrecoCusto * (1d + (1d / 3));
}

and from there, to use the new constructor, in ListaProdutos.GetList(), would look like this:

List<Produto> listaProdutos = new List<Produto>()
{
    new Produto(12.00) { Id = 1, Nome = "Arroz", /*PrecoCusto = 12,*/ ... },
    new Produto(5.00)  { Id = 2, Nome = "Leite", /*PrecoCusto = 5,*/ ... },
};

This case PrecoVenda is not always exactly the same as PrecoCusto + PrecoCusto / 3. You never know when the owner of the company wants to increase their profit margin, do you? P

Browser other questions tagged

You are not signed in. Login or sign up in order to post.