Reputation: 11127
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?
Upvotes: 1
Views: 6302
Reputation: 1248
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
Upvotes: 1
Reputation: 1503829
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.
Upvotes: 7
Reputation: 13495
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);
Upvotes: 6