1

I have the following classes:

public class Product
{
    public int ProductID { get; set; }
    public string Name { get; set; }
    public string Description { get; set; }
    public decimal Price { get; set; }
    public string Category { set; get; }
}

public class LinqValueCalculator
{
    public decimal ValueProducts(IEnumerable<Product> products)
    {
        return products.Sum(p => p.Price);
    }
}

public class ShoppingCart
{
    private LinqValueCalculator calc;
    public ShoppingCart(LinqValueCalculator calcParam)
    {
        calc = calcParam;
    }
    public IEnumerable<Product> Products { get; set; }
    public decimal CalculateProductTotal()
    {
        return calc.ValueProducts(Products);
    }
}

In ShoppingCart class, there's private LinqValueCalculator calc; from my understanding we are creating an object from that class, but how is this different than private LinqValueCalculator calc = new LinqValueCalculator();

Which one should be preferred...where and why?

Vahid Amiri
  • 10,769
  • 13
  • 68
  • 113
  • The code you posted is not creating new object instances. Look for code which is instantiating the `ShoppingCart`, it will create the instance of `LinqValueCalculator` to pass it to the cart's constructor (or, it's instantiated elsewhere). Unless you are using dependency injection, which you most likely aren't since `LinqValueCalculator` is not an interface or an abstract class. – vgru Oct 24 '15 at 11:30
  • @Groo Actually later in the book (Pro ASP.NET MVC 5) author uses DI (ninject) – Vahid Amiri Oct 24 '15 at 11:35

3 Answers3

7

In ShoppingCart class, there's private LinqValueCalculator calc; from my understanding we are creating an object from that class

No, it doesn't. It declares a variable of that type, but it doesn't create any objects. Initially, that will default to null... but it's important to differentiate between objects, variables and references. For example, you could have two variables but one object...

LinqValueCalculator calc1 = new LinqValueCalculator();
LinqValueCalculator calc2 = calc1;

Here both variables have the same value - which is a reference to the single object it creates.

Community
  • 1
  • 1
Jon Skeet
  • 1,421,763
  • 867
  • 9,128
  • 9,194
  • And what about the parameter `LinqValueCalculator calcParam`. is that a variable too? – Vahid Amiri Oct 24 '15 at 11:19
  • @vsg23434245: Yes, parameters are local variables whose initial values are provided by the caller, basically. – Jon Skeet Oct 24 '15 at 11:27
  • 1
    @vsg23434245: I'd strongly advise you to follow the link in the answer, by the way... and don't try to think in C++ terms :) – Jon Skeet Oct 24 '15 at 11:28
6

In the code below you are assigning the reference calc in the class ShoppingCart to the reference passed in calcParam. Initially the calc field is null and once the constructor runs it is assigned to calcParam. Both references point to the same object so changes vie either reference are reflected in the object.

private LinqValueCalculator calc;
public ShoppingCart(LinqValueCalculator calcParam)
{
    calc = calcParam;
}

The code below creates a new LinqValueCalculator object only referred to from this class. No one else has a reference to this object and therefore only the shopping cart can use the object.

private LinqValueCalculator calc = new LinqValueCalculator();

Either usage can be useful depending on whether you want a shared calculator and whether you want to control its lifetime in the ShoppingCart class.

If you have a C++ background, C# references are more like a C++ pointer rather than a reference.

So assuming LinqValueCalculator has a default constructor, creating a ShoppingCart is likely to look like this:

 LinqValueCalculator calc = new LinqValueCalculator();
 ShoppingCart cart = new ShoppingCart(calc);
NeddySpaghetti
  • 13,187
  • 5
  • 32
  • 61
  • Very well explained. So `LinqValueCalculator calcParam` is creating an object and passing it to ShoppingCart constructor? – Vahid Amiri Oct 24 '15 at 11:24
  • `LinqValueCalculator calcParam` is just passing the object, it may be created before constructing the `ShoppingCart`, or if not created it will be null. – NeddySpaghetti Oct 24 '15 at 11:26
  • 1
    I updated to answer to show how you'd create the shopping cart with a non `null` `LinqValueCalculator` – NeddySpaghetti Oct 24 '15 at 11:29
1

This is an architecture decision only. The reason behind put LinqValueCalculator as a parameter in the ShoppingCard constructor is because the author wants to use Dependency Injection. When you use DI, you move the responsability of lifetime of the object outside ShoppingCard class, this gives more control in the future, because, every object receives it's dependencies from outside, but they only consumes it, not instantiates.

That making it easy to follow the Single Responsibility Principle. Usually another object called composer or catalog has the responsability to instantiate all dependencies and supply them to the correspond objects.

Benefits of Dependency Injection - Programmers Exchange

Community
  • 1
  • 1
Mr Rivero
  • 1,248
  • 7
  • 17
  • I'm sorry to say, but you overshot the asker's apparent knowledge on this topic by miles. The asker already has a problem keeping variables and objects apart (hopefully the other answers cleared that up by now), so introducing dependency injection really won't help. – Wormbo Oct 24 '15 at 13:58