IzzyTwinkly
asked on
property-based initialization.
Hi experts,
from the code below, Initializing Product looks little bit different from what I have done.
1. In GetSampleProducts(), return statement comes first.
2. Also it uses {} instead of () to initialize each product.
3. we need a private parameterless constructor Product(){}.
I guess that it's because it uses properties instead instance variable. Can anybody explain these in more detail please?
from the code below, Initializing Product looks little bit different from what I have done.
1. In GetSampleProducts(), return statement comes first.
2. Also it uses {} instead of () to initialize each product.
3. we need a private parameterless constructor Product(){}.
I guess that it's because it uses properties instead instance variable. Can anybody explain these in more detail please?
class Product
{
public string Name { get; private set; }
public decimal Price { get; private set; }
public Product(string name, decimal price)
{
Name = name;
Price = price;
}
Product() { }
public static List<Product> GetSampleProducts()
{
return new List<Product>
{
new Product {Name ="West Side Stroy", Price = 9.99m},
new Product {Name = "Assassins", Price = 14.99m},
new Product {Name = "Frogs", Price = 13.99m},
new Product {Name = "Sweeney Todd", Price = 10.99m}
};
}
}
So lets have a little fun with your code:
using System;
using System.Collections.Generic;
using System.Linq;
namespace EE_Q28705107
{
class Program
{
static void Main(string[] args)
{
var products = Product.GetSampleProducts();
// I'm going to add a new Product to my products list.
products.Add(new Product("Mad Max", 49.99m) { Quantity = 5 });
foreach (var product in products)
Console.WriteLine(product);
Console.WriteLine(Product.Checkout(products));
Console.ReadLine();
}
}
class Product
{
public string Name { get; private set; }
public decimal Price { get; private set; }
public int Quantity { get; set; }
public decimal Total { get { return Price * Quantity; } }
public Product(string name, decimal price)
{
Console.WriteLine("IN CONSTRUCTOR WITH PARAMETERS");
Name = name;
Price = price;
}
Product()
{
Console.WriteLine("IN PARAMETERLESS CONSTRUCTOR");
}
public static List<Product> GetSampleProducts()
{
return new List<Product>
{
new Product { Name = "West Side Stroy", Price = 9.99m, Quantity = 1 },
new Product { Name = "Assassins", Price = 14.99m, Quantity = 2 },
new Product { Name = "Frogs", Price = 13.99m, Quantity = 1 },
new Product { Name = "Sweeney Todd", Price = 10.99m, Quantity = 2 }
};
}
public static string Checkout(IEnumerable<Product> products)
{
return string.Format("Total cost: {0:C2}", products.Sum(x => x.Total));
}
public override string ToString()
{
return string.Format("{0} of {1} at {2:C2} = {3:C2}", Quantity, Name, Price, Total);
}
}
}
Produces the following output --saige-
ASKER
Thanks Saige!
I am still little bit confused.
In your answer for question 3, you said, "A parameter less constructor is needed if you plan on declaring a new instance of a class without passing parameters and have an existing constructor defined that accepts parameters. "
When we do 'new Product {Name ="West Side Stroy", Price = 9.99m}', I thought that we are passing 2 parameters. But it seems that this line calls parameterless constructor, right?
hum...
I am still little bit confused.
In your answer for question 3, you said, "A parameter less constructor is needed if you plan on declaring a new instance of a class without passing parameters and have an existing constructor defined that accepts parameters. "
When we do 'new Product {Name ="West Side Stroy", Price = 9.99m}', I thought that we are passing 2 parameters. But it seems that this line calls parameterless constructor, right?
hum...
ASKER CERTIFIED SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
To further prove my point, let's say we now decide we don't want to define a constructor that accepts parameters, matter of fact, we don't want to define any constructors of any kind. What do you think will happen now?
Well let's find out -It appears as if the compiler does not like that we are trying to use a constructor. But remember a class (by default) does not need a constructor/destructor as an implied public, parameter-less, constructor/destructor is generated by default. Let's test that theory by trying to just initialize our instances with a parameter-less constructor.Uh-oh now we got a new error. The implied constructor is public but the accessors (the setters) for two of the properties (Name and Price) are not. These are marked as private, this means that only a class defined method can access the properties. So we can do one of a few things:
1, We can make the setters public by removing the private declaration.
2. We can create a new constructor that takes the parameters.
3. We can create a method that allows us to set the parameters.
For the sake of simplicity, let's remove the private declaration from the property setters (I will leave you with the third option as we have already proven the second option works).
And once again, everything is right in the world -Now let's run it and see what output we get -And finally here is the updated code -
Well let's find out -It appears as if the compiler does not like that we are trying to use a constructor. But remember a class (by default) does not need a constructor/destructor as an implied public, parameter-less, constructor/destructor is generated by default. Let's test that theory by trying to just initialize our instances with a parameter-less constructor.Uh-oh now we got a new error. The implied constructor is public but the accessors (the setters) for two of the properties (Name and Price) are not. These are marked as private, this means that only a class defined method can access the properties. So we can do one of a few things:
1, We can make the setters public by removing the private declaration.
2. We can create a new constructor that takes the parameters.
3. We can create a method that allows us to set the parameters.
For the sake of simplicity, let's remove the private declaration from the property setters (I will leave you with the third option as we have already proven the second option works).
And once again, everything is right in the world -Now let's run it and see what output we get -And finally here is the updated code -
using System;
using System.Collections.Generic;
using System.Linq;
namespace EE_Q28705107
{
class Program
{
static void Main(string[] args)
{
var products = Product.GetSampleProducts();
// I'm going to add a new Product to my products list.
products.Add(new Product { Name = "Mad Max", Price = 49.99m, Quantity = 5 });
foreach (var product in products)
Console.WriteLine(product);
Console.WriteLine(Product.Checkout(products));
Console.ReadLine();
}
}
class Product
{
public string Name { get; set; }
public decimal Price { get; set; }
public int Quantity { get; set; }
public decimal Total { get { return Price * Quantity; } }
// Uh-oh, no constructors defined...
//public Product(string name, decimal price)
//{
// Console.WriteLine("IN CONSTRUCTOR WITH PARAMETERS");
// Name = name;
// Price = price;
//}
// Removed parameter-less constructor
//Product()
//{
// Console.WriteLine("IN PARAMETERLESS CONSTRUCTOR");
//}
public static List<Product> GetSampleProducts()
{
return new List<Product>
{
new Product { Name = "West Side Stroy", Price = 9.99m, Quantity = 1 },
new Product { Name = "Assassins", Price = 14.99m, Quantity = 2 },
new Product { Name = "Frogs", Price = 13.99m, Quantity = 1 },
new Product { Name = "Sweeney Todd", Price = 10.99m, Quantity = 2 }
};
}
public static string Checkout(IEnumerable<Product> products)
{
return string.Format("Total cost: {0:C2}", products.Sum(x => x.Total));
}
public override string ToString()
{
return string.Format("{0} of {1} at {2:C2} = {3:C2}", Quantity, Name, Price, Total);
}
}
}
-saige-
And finally, to further illustrate that we are not using a constructor but, rather, initializing properties, let's say we remove the Quantity property initialization on the Product instances that are created by the GetSampleProducts() method [remember we are still using the implied public parameter-less constructor]. What do you think happens then?
using System;
using System.Collections.Generic;
using System.Linq;
namespace EE_Q28705107
{
class Program
{
static void Main(string[] args)
{
var products = Product.GetSampleProducts();
// I'm going to add a new Product to my products list.
products.Add(new Product { Name = "Mad Max", Price = 49.99m, Quantity = 5 });
foreach (var product in products)
Console.WriteLine(product);
Console.WriteLine(Product.Checkout(products));
Console.ReadLine();
}
}
class Product
{
public string Name { get; set; }
public decimal Price { get; set; }
public int Quantity { get; set; }
public decimal Total { get { return Price * Quantity; } }
// Uh-oh, no constructors defined...
//public Product(string name, decimal price)
//{
// Console.WriteLine("IN CONSTRUCTOR WITH PARAMETERS");
// Name = name;
// Price = price;
//}
// Removed parameter-less constructor
//Product()
//{
// Console.WriteLine("IN PARAMETERLESS CONSTRUCTOR");
//}
public static List<Product> GetSampleProducts()
{
return new List<Product>
{
new Product { Name = "West Side Stroy", Price = 9.99m },
new Product { Name = "Assassins", Price = 14.99m },
new Product { Name = "Frogs", Price = 13.99m },
new Product { Name = "Sweeney Todd", Price = 10.99m }
};
}
public static string Checkout(IEnumerable<Product> products)
{
return string.Format("Total cost: {0:C2}", products.Sum(x => x.Total));
}
public override string ToString()
{
return string.Format("{0} of {1} at {2:C2} = {3:C2}", Quantity, Name, Price, Total);
}
}
}
Produces the following output --saige-
ASKER
Wow. Thanks for your time and explanation!!!
Open in new window
Logically is the same as:Open in new window
2. The bracket's define a initialization process. Think of this as the same thing as:
Open in new window
The difference here is that you are initializing a reference item, so you have to tell the initializer which property[ or properties] you are declaring the value for.3. A parameter less constructor is needed if you plan on declaring a new instance of a class without passing parameters and have an existing constructor defined that accepts parameters. The fact that the parameter less constructor is marked private simply means that anything outside of the Product class cannot declare a new instance without using the constructor that accepts parameters.
-saige-