I have the following code:
namespace QuantStrats
{
class Program
{
static void Main(string[] args)
{
string FilePath = "C:\\Users\\files\\DJ.csv";
StreamReader streamReader = new StreamReader(FilePath);
string line;
List<Data> Data = new List<Data>();
while ((line = streamReader.ReadLine()) != null)
{
Data Tick = new Data();
string [] values = line.Split(',');
Tick.SetFields(values[1], values[2]);
Data.Add(Tick);
}
for (int ii = 0; ii < Data.Count; ii++)
{
Data TickDataValues = new Data();
TickDataValues = Data[ii];
Console.Write("TIME :" + TickDataValues.time + " Price : " + TickDataValues.price + Environment.NewLine);
}
Console.ReadLine();
}
}
class Data
{
public DateTime time
{
get { return this.time; }
set
{
this.time = value;
}
}
public double price
{
get { return this.price; }
set
{
this.price = value;
}
}
public void SetFields(string dateTimeValue, string PriceValue)
{
try
{
this.time = Convert.ToDateTime(dateTimeValue);
}
catch
{
Console.WriteLine("DateTimeFailed " + dateTimeValue + Environment.NewLine);
}
try
{
this.price = Convert.ToDouble(PriceValue);
}
catch
{
Console.WriteLine("PriceFailed " + PriceValue + Environment.NewLine);
}
}
}
}
But I get a stack overflow exception.
I know it is because I am not doing my get and sets correctly and am entering an infinite loop, but I cannot see why exactly this is happening?
public DateTime time
{
get { return this.time; }
set
{
this.time = value;
}
}
you aren't using backing fields, but setting the property itself from within the property setter.
You can fix this by using 1) an auto property
public DateTime Time { get; set; }
or 2) a backing field
private DateTime _time;
public Datetime Time
{
get { return _time; }
set { _time = value; }
}
they both equate to the same code.
For an explanation, when you get time in your code:
get { return this.time; }
it has to retrieve the value of time to return. It does that by calling the get on time, which has to get retrieve the value of time, etc.
I cannot see why exactly this is happening?
public double price
{
get { return this.price; }
set
{
this.price = value;
}
}
When you "get" price, the getter for price is called, which calls the getter for price, which calls the getter for price, which...
Just use auto-implement properties if you don't want to mess with a backing field:
public DateTime Time {get; set;}
public double Price {get; set;}
Some other observations:
The standard convention for property names is to start them with a capital letter, which is why I changed your properties to Time and Price in my examples.
You may want to consider using decimal for a property like Price if you do any floating-point math, since double has some slight imprecision when representing decimal numbers like 1.1. decimal will store the number exacly without any loss of precision.
Just writing to the console in a catch block seems incorrect. You are basically ignoring the error (from a logic flow sense). Rather than accepting strings in the class and parsing them, I would do the validation in the calling code and making sure the inputs are valid before passing them to the class.
Properties getters and setters are really just getXXX and setXXX methods (that's how they are compiled). Because you set the property from the property itself, it is if you were recurring endlessly on a method.
public DateTime time()
{
return time();
}
As stated by other answers, you can use backing fields or auto-implemented properties.
Related
I have a wpf application in C# which is used to book houses.
I want to calculate the total price of a reservation. I have 2 datetimes: Check in & Check Out.
The calculation I need to use = (CheckOut - CheckIn).TotalDays * BnB.Price
BnB.Price is the price per night.
I want the totalprice to update live in the guest View.
So whenever I change the check in and out dates the total price automatically changes.
This is my Reservation Model:
private double _totalprice { get; set; }
private DateTime _checkIn { get; set; }
private DateTime _checkOut { get; set; }
public double TotalPrice
{ get => _totalprice; set { _totalprice = value; Notify("TotalPrice"); } }
public DateTime CheckIn
{ get => _checkIn; set { if (value < _checkOut) { _checkIn = value; }; Notify("CheckIn"); } }
public DateTime CheckOut
{ get => _checkOut; set { if (value > _checkIn) { _checkOut = value; }; Notify("CheckOut"); } }
If I missed something please let me know!
Based on the comments in your question, BnB is a member of the reservation model. Given that, you can change TotalPrice to a readonly property, a property without a set method, and just caluclate the total in the get method. Then, in the setters for CheckIn and CheckOut, call Notify("TotalPrice") to update the UI. You also need to call Notify("TotalPrice") in the setter for BnB, since that member participates in the calculation of TotalPrice.
This assumes that the Reservation Model implements INotifyPropertyChanged and that Notify invokes the PropertyChanged event.
public class Reservation : INotifyPropertyChanged
{
private BnB? _bnb;
private DateTime _checkIn;
private DateTime _checkOut;
public double TotalPrice
{
// Instead of using a field, just calculate TotalPrice on the fly.
get
{
// Check for nulls - since _bnb is the only thing that is
// is nullable in the calculation, it is the only thing we
// need to check.
if (BnB== null)
{
return 0;
}
return (CheckOut - CheckIn).TotalDays * BnB.Price;
}
}
public BnB BnB
{
get => _bnb;
set
{
if (_bnb != value)
{
_bnb = value;
Notify(nameof(BnB));
Notify(nameof(TotalPrice));
}
}
}
public DateTime CheckIn
{
get => _checkIn;
set
{
if (value != _checkIn && value < _checkOut)
{
// I've changed the check to ensure that the new value isn't the
// same as the current value. No sense running this code if nothing
// has actually changed.
_checkIn = value;
}
// Without knowing what Notify does exactly, I can't say for sure. But
// if it is only invoking the PropertyChanged event then these two lines
// should probably be placed inside the if statement. There isn't any
// point to notifying the UI that a change happened if a change didn't
// actually happen.
Notify(nameof(CheckIn));
// You can notify the UI to update TotalPrice within a setter for a
// different property.
Notify(nameof(TotalPrice));
}
}
public DateTime CheckOut
{
get => _checkOut;
set
{
if (value != _checkOut&& value > _checkIn)
{
_checkOut = value;
}
// These might make more sense inside the if statement as well.
Notify(nameof(CheckOut));
Notify(nameof(TotalPrice));
}
}
// Other members of the Reservation model.
}
If you really need to have TotalPrice be a property with a getter / setter and a backing field, then just set the TotalPrice property when you set CheckIn, CheckOut, or BnB.
public class Reservation
{
private BnB? _bnb;
private DateTime _checkIn;
private DateTime _checkOut;
private double _totalPrice;
public double TotalPrice
{
get => _totalPrice;
set
{
if (_totalPrice != value)
{
_totalPrice = value;
Notify("TotalPrice");
}
}
}
public BnB BnB
{
get => _bnb;
set
{
if (_bnb != value)
{
_bnb = value;
Notify(nameof(BnB));
TotalPrice = CalculateTotalPrice();
}
}
}
public DateTime CheckIn
{
get => _checkIn;
set
{
if (value != _checkIn && value < _checkOut)
{
// I've changed the check to ensure that the new value isn't the
// same as the current value. No sense running this code if nothing
// has actually changed.
_checkIn = value;
}
// Without knowing what Notify does exactly, I can't say for sure. But
// if it is only invoking the PropertyChanged event then these two lines
// should probably be placed inside the if statement. There isn't any
// point to notifying the UI that a change happened if a change didn't
// actually happen.
Notify(nameof(CheckIn));
// You can notify the UI to update TotalPrice within a setter for a
// different property.
TotalPrice = CalculateTotalPrice();
}
}
public DateTime CheckOut
{
get => _checkOut;
set
{
if (value != _checkOut&& value > _checkIn)
{
_checkOut = value;
}
// These might make more sense inside the if statement as well.
Notify(nameof(CheckOut));
TotalPrice = CalculateTotalPrice();
}
}
private double CalculateTotalPrice()
{
if (BnB== null)
{
return 0;
}
return (CheckOut - CheckIn).TotalDays * BnB.Price;
}
// Other members of the Reservation model.
}
Also, on a side note you might want to consider switching from double to decimal to represent currency.
I have a List that contains a series of transaction objects. What I'm trying to do is to display these transaction objects in a Datagridview control on loading a form, basically the Datagridview should represent something of a transaction register to display the data for each of the transaction objects in the list.
I must admit to a lack of experience when it comes to using Datagridviews and I'm having some difficulty with understanding what I need to do here.
My question is, how do I go about getting the details of each of the objects in the list to display in the Datagridview?
Here is my code.
First the transaction class:
public class Transaction
{
// Class properties
private decimal amount;
private string type;
private decimal balance;
private string date;
private string transNum;
private string description;
// Constructor to create transaction object with values set.
public Transaction(decimal amount, string type, decimal currBal, string date, string num, string descrip)
{
this.amount = amount;
this.type = type;
this.balance = currBal;
this.date = date;
this.transNum = num;
this.description = descrip;
}
// Get and Set accessors to allow manipulation of values.
public decimal Amount
{
get
{
return amount;
}
set
{
amount = value;
}
}
public string Type
{
get
{
return type;
}
set
{
type = value;
}
}
public decimal Balance
{
get
{
return balance;
}
set
{
balance = value;
}
}
public string Date
{
get
{
return date;
}
set
{
date = value;
}
}
public string TransNum
{
get
{
return transNum;
}
set
{
transNum = value;
}
}
public string Description
{
get
{
return description;
}
set
{
description = value;
}
}
public decimal addCredit(decimal balance, decimal credit)
{
decimal newBalance;
newBalance = balance + credit;
return newBalance;
}
public decimal subtractDebit(decimal balance, decimal debit)
{
decimal newBalance;
newBalance = balance - debit;
return newBalance;
}
}
}
Now the code for the "Register" form:
public partial class Register : Form
{
List<Transaction> tranList = new List<Transaction>();
public Register(List<Transaction> List)
{
InitializeComponent();
this.tranList = List;
}
private void Register_Load(object sender, System.EventArgs e)
{
//regView represents the Datagridview that I'm trying to work with
regView.AutoSize = true;
regView.DataSource = tranList;
regView.Rows.Add(tranList[0]);
}
}
And here's the output I get.
There's really two high level approaches to this.
1) Add the manually created rows directly to the DataGridView. In this case, you have to manually update/remove them as things change. This approach is "ok" if you don't intend to alter/change the content of the display after you initialize it. It becomes untenable if you do.
To add it directly, you need to create a DataGridViewRow, and populate it with the individual values, and then add the DataGridViewRow to the DataGridView.Rows.
2) Data bind the DGV. There's many articles about databinding to a DataGridView. In some cases, it's easier to just add your data to a DataTable, and then extract a DataView from that, and bind the DataGridView to the DataView. Other people find it easier to directly bind to a collection.
CodeProject has a decent article to get you started down that path, but a quick Google search will yield many other articles.
http://www.codeproject.com/Articles/24656/A-Detailed-Data-Binding-Tutorial
use as DGV:
DataGridView groupListDataGridView;
column:
DataGridViewTextBoxColumn groupListNameColumn;
column setup should be like this:
groupListNameColumn.DataPropertyName = "name";
use this property, else all columns will be added.
groupListDataGridView.AutoGenerateColumns = false;
populate like this:
private void populateGroupList() {
groupListDataGridView.DataSource = null;
formattedGroupList = new SortableBindingList<DataGridGroupObject>();
foreach (GroupObject go in StartUp.GroupList) {
DataGridGroupObject dggo = new DataGridGroupObject();
dggo.id = go.Id;
dggo.name = go.Name;
formattedGroupList.Add(dggo);
}
groupListDataGridView.DataSource = formattedGroupList;
groupListDataGridView.Invalidate();
}
and model:
public class DataGridGroupObject
{
public int id { get; set; } //this will be match id column
public string name { get; set; } // this will be match name column
}
Simply add using System.Linq; at the top. Then you can do this:
//This will create a custom datasource for the DataGridView.
var transactionsDataSource = tranList.Select(x => new
{
Amount = x.amount,
Type = x.type,
Balance = x.balance,
Date = x.date,
TransNum = x.transNum
Description = x.description
}).ToList();
//This will assign the datasource. All the columns you listed will show up, and every row
//of data in the list will populate into the DataGridView.
regView.DataSource = transactionsDataSource;
Working on a program for class, and am about 95% complete, but have run into a roadblock. I've got a Flight class that holds information about the flight, as well as a seating chart. Using a windows form listbox to select from the flight objects I created by reading from a text file. I can get values for every property from the class object, except for one, SeatChart.
Here's the pertinent code in the main program:
private void lstFlights_SelectedIndexChanged(object sender, EventArgs e)
{
curFlight = (Flight)lstFlights.SelectedItem;
DisplayNewFlightChart();
}
private void DisplayNewFlightChart()
{
int seats = curFlight.Rows * curFlight.Seats;
lstSeatingChart.Items.Clear();
string[] seatChart = curFlight.SeatChart;
for (int x = 0; x <= seats; x++)
{
lstSeatingChart.Items.Add("Seat " + (x + 1) + " " + seatChart[x]);
}
}
And here is the code from the class:
class Flight
{
private string mPlane;
private string mDepartureTime;
private string mDestination;
private int mRows;
private int mSeats;
private string[] mSeatChart;
public Flight()
{
}
// Create the overloaded Constructor
public Flight(string planeType, string departureTime,
string destination, int numRows,
int numSeatsPerRow)
{
this.Plane = planeType;
this.DepartureTime = departureTime;
this.Destination = destination;
this.Rows = numRows;
this.Seats = numSeatsPerRow;
this.SeatChart = mSeatChart;
mSeatChart = new string[Rows * Seats];
for (int seat = 0; seat <= mSeatChart.GetUpperBound(0); seat++)
{
mSeatChart[seat] = "Open";
}
}
public string Plane
{
get { return mPlane; }
set { mPlane = value; }
}
public string DepartureTime
{
get { return mDepartureTime; }
set { mDepartureTime = value; }
}
public string Destination
{
get { return mDestination; }
set { mDestination = value; }
}
public int Rows
{
get { return mRows; }
set { mRows = value; }
}
public int Seats
{
get { return mSeats; }
set { mSeats = value; }
}
public string[] SeatChart
{
get { return mSeatChart; }
set { mSeatChart = value; }
}
public void MakeReservation(string passName, int seat)
{
bool seatTaken = false;
if (mSeatChart[seat] != "Open") seatTaken = true;
if (passName != "" && seatTaken == false)
{
mSeatChart[seat] = passName;
}
else
{
MessageBox.Show("Please Enter a Passenger Name, in an unreserved seat");
}
}
It's telling me the curFlight.SeatChart is null, even though I can pull .Rows and .Seats from the curFlight just fine. I have no clue why .SeatChart is messing up. lstFlights is the list of flight objects pulled from the text file, and lstSeatingChart is where I want to display a list of seats.
You are setting SeatChart to mSeatChart, which is null at that time. So no reference to an object is made for this.SeatChart.
After that you initialize mSeatChart and fill it.
You should move setting this.SeatChart after initializing mSeatChart.
mSeatChart = new string[Rows * Seats];
this.SeatChart = mSeatChart;
Edit:
In addition, SeatChart is the property and mSeatChart is the member variable. SeatChart will be used to expose mSeatChart, so it's really weird to set SeatChart with mSeatChart. So weird that I didn't even think you were doing that.
So in your case leave the following out in the constructor:
this.SeatChart = mSeatChart;
I think the actual cause of your issue is somewhere else in the code, where you initiate Flight and fill the list. If I understand correctly you get a null reference error on the concatenation in the for loop?
string[] seatChart = curFlight.SeatChart;
for (int x = 0; x <= seats; x++)
{
lstSeatingChart.Items.Add("Seat " + (x + 1) + " " + seatChart[x]);
}
Check where you initate each Flight object. I bet you are using the empty constructor: new Flight()
Remove the empty constructor, because you don't expect empty values apparently. And if you really need the empty constructor then either initiate all member variables as expected or perform a null check wherever you want to use them.
And once you found the cause, make sure you change the for loop to
for (int x = 0; x < seats; x++)
since you are checking for the number of seats and do a zero-based loop. If x = seats you would have performed the loop seats + 1 times (rows*seats + 1).
If your code relies on a particular property never being null, you need to make sure it is initialized in all constructors.
Based on the logic of your class, I would suggest you shouldn't have a parameter less constructor. It doesn't make sense to have a flight that didn't have a known number of seats (in your implementation at least).
Also some style things.
You don't need to declare your private instance variables. Just use
public string destination {get; set;}
Declare "open" as a class constant and use that constant rather than the hard coded string value.
I currently have a listbox that displays the date, type of cake and size. I want to add cost to the listbox, but I am having trouble. It currently displays zero for the cost. The cost is displayed in a label (lblRoundCost). I have a base class named Cake and two subclasses RoundCake and SquareCake. I'm not sure if this code is correct for the base class:
class Cake
{
private const int CostOfFoodPerPerson = 25;
public int size;
private bool chocolateIcing;
protected DateTime cakeDate;
decimal cost;
public Cake(int numberOfPeople, bool chocolateIcing, DateTime cakeDate)
{
this.chocolateIcing = chocolateIcing;
Size = size;
this.cakeDate = cakeDate;
Cost = cost;
}
public virtual decimal Cost
{
get { return cost; }
set { cost = value; }
}
public virtual int Size
{
get { return size; }
set { size = value; }
}
public virtual bool ChocolateIcing
{
set { chocolateIcing = value; }
}
public virtual decimal CalculateCost()
{
decimal CostOfIcing = 0;
if (chocolateIcing)
CostOfIcing = (Size * 1.5M) + 10M;
else
CostOfIcing = 0;
decimal TotalCost = CostOfIcing + CostOfFoodPerPerson;
return TotalCost;
}
public DateTime CakeDate
{
set { cakeDate = value; }
}
}
}
RoundCake code
class RoundCake : Cake
{
bool fruitOption;
public RoundCake(int size, bool fruitOption, bool chocolateIcing, DateTime cakeDate)
: base(size, chocolateIcing, cakeDate)
{FruitOption = fruitOption;}
public bool FruitOption
{
set { fruitOption = value; }
}
public override decimal CalculateCost()
{
decimal totalCost;
if (fruitOption)
{
totalCost = base.CalculateCost();
return totalCost + (totalCost * .05M);
}
else
{
totalCost = base.CalculateCost() ;
return totalCost;
}
}
public override string ToString()
{
return String.Format("{0,-20}{1,2}{2,20}{2,20}", cakeDate.ToShortDateString(), "RC",Size,Cost);
}
Form1 code
private void btnRound_Click_1(object sender, EventArgs e)
{
lstCake.Items.Add(roundCake);
}
roundCake = new RoundCake((int)nudRound.Value, chbFruit.Checked, chbChocoRound.Checked,
dtpRound.Value.Date);
lblRoundCost.Text = roundCake.CalculateCost().ToString("c");
The reason you're seeing 0 is because you never actually assign anything to Cost, and the default for decimal is 0.
Here's what's happening:
In your base constructor, you have:
Cost = cost;
However, cost is never initialized in the class and it's not passed in via the constructor. So in the base it's 0.
The same thing happens with the inheriting class - Cost is never specified, so it's still going to be 0 (even if there wasn't a base class, it'd still be 0).
Now, in this line of code:
lblRoundCost.Text = roundCake.CalculateCost().ToString("c");
You're assigning the value calculated by CalculateCost() to the Label, but you're never persisting that value in the the class:
public override decimal CalculateCost()
{
decimal totalCost;
if (fruitOption)
{
totalCost = base.CalculateCost();
return totalCost + (totalCost * .05M);
}
else
{
totalCost = base.CalculateCost() ;
return totalCost;
}
}
You're returning a value, but not assigning it to the class member cost. The base implementation does the same thing.
There a number of ways to solve this. Here's one (this is a pretty simple one, and to be honest it has a bit of a code smell to me, but it'll server as an example):
Modify the CalculateCost() method to update the cost field:
public virtual void CalculateCost()
{
decimal CostOfIcing = 0;
if (chocolateIcing)
CostOfIcing = (Size * 1.5M) + 10M;
else
CostOfIcing = 0;
decimal cost = CostOfIcing + CostOfFoodPerPerson;
}
Note that this doesn't return a type anymore (you may have it still do so, it really depends a lot on your overall design, so pick the path that works best for your design). Don't forget to make this change in the inheriting class's implementation as well.
Now you simply need to call the CalculateCost() method and you will have the cost available, and you can use the property to get the cost for assignment to Labels or whatever else you need, and it will show up in your overridden ToString() method.
Again, there are multiple ways to solve this, and they depend on a mix of OOP principles and your design needs. My main intention with this answer was to demonstrate why cost was showing up as zero.
I am upgrading an existing application that has implemented a home-brew Constants class in its business and datalayer objects.
I want to replace this with Nullable types and do-away with the constants class, that looks like this, but with all non-nullable data types:
class Constants
{
public static int nullInt
{
get { return int.MinValue; }
}
}
These constants vaules are used as defaults on almost all the object properties like this:
private decimal _unitPrice = Constants.nullInt;
public decimal UnitPrice
{
get { return _unitPrice; }
set { _unitPrice = (value == null) ? Constants.nullInt : value; }
}
This causes some confusion on saving object properties to the Db as all decimal's and ints have to be checked for psudo null values or else you save things like int.MinValue to the Db.
private void Save()
{
//Datalayer calls and other props omitted
SqlParameter sqlParm = new SqlParameter();
sqlParm.Value = (this.UnitPrice == Constants.nullInt) ? DBNull.Value : (object)this.UnitPrice;
}
Ok so now the question.. I want to change things around using Nullable value types as in my example below, will the change in a property from a decimal to a decimal? affect any code thats implementing these objects?
public decimal? UnitPrice { get; set; }
private void Save()
{
//Datalayer calls and other props omitted
SqlParameter sqlParm = new SqlParameter();
sqlParm.Value = this.UnitPrice ?? DBNull.Value;
}
EDIT: Thanks for the double check of my refactor, and yes the null check on the SET of the property in the original code would be redundant. I still want to know if code that implements this object could have any issues from the change of type to decimal? from decimal
public decimal? UnitPrice { get; set; }
private void Save()
{
//Datalayer calls and other props omitted
SqlParameter sqlParm = new SqlParameter();
sqlParm.Value = this.UnitPrice ?? DBNull.Value;
}
I find this absolutely ok. This is how it is supposed to work.
I'm a little unclear as to the implementation of your above property set method as a decimal can never be null so this test is redundant I think. I'm including some sample code that can be dropped into a Console application that should clear things up for you.
You will experience very little refactoring of your code due to switching over to the nullable data types. This will be a good move on your part in cleaning up your code and avoiding the potential pitfalls of your current implementation.
If nothing else, the performance gains you'll receive would likely make the effort worth your while. Nothing will be completely plug-n-play so to speak but if you look at the below code you'll see there's very little impact in the scenarios you've provided.
Example
using System;
using System.Data.SqlClient;
namespace NullableTypes
{
class Program
{
static class Constants
{
public static decimal NullDecimal
{
get { return decimal.MinValue; }
}
}
public class ProductTheOldWay
{
public string Name { get; set; }
public decimal UnitPrice { get; set; }
public ProductTheOldWay()
{
Name = string.Empty;
UnitPrice = Constants.NullDecimal;
}
public override string ToString()
{
return "Product: " + Name + " Price: " +
((UnitPrice == Constants.NullDecimal)
? "Out of stock"
: UnitPrice.ToString());
}
public void Save()
{
//Datalayer calls and other props omitted
var sqlParm = new SqlParameter
{
Value = (UnitPrice == Constants.NullDecimal)
? DBNull.Value
: (object)UnitPrice
};
//save to the database...
Console.WriteLine("Value written to the database: " + sqlParm.Value);
}
}
public class ProductTheNewWay
{
public string Name { get; set; }
public decimal? UnitPrice { get; set; }
public ProductTheNewWay()
{
Name = string.Empty;
}
public override string ToString()
{
return "Product: " + Name + " Price: " +
((UnitPrice.HasValue)
? UnitPrice.ToString()
: "Out of stock");
}
public void Save()
{
//Datalayer calls and other props omitted
var sqlParm = new SqlParameter
{
Value = UnitPrice
};
//save to the database...
Console.WriteLine("Value written to the database: " + sqlParm.Value);
}
}
static void Main()
{
var oldProduct1 = new ProductTheOldWay
{
Name = "Widget",
UnitPrice = 5.99M
};
var oldProduct2 = new ProductTheOldWay
{
Name = "Rare Widget",
UnitPrice = Constants.NullDecimal // out of stock
};
Console.WriteLine(oldProduct1);
Console.WriteLine(oldProduct2);
Console.WriteLine("Saving...");
oldProduct1.Save();
oldProduct2.Save();
Console.ReadLine();
var newProduct1 = new ProductTheNewWay
{
Name = "Widget",
UnitPrice = 5.99M
};
var newProduct2 = new ProductTheNewWay
{
Name = "Rare Widget"
/* UnitPrice = null by default */
};
Console.WriteLine(newProduct1);
Console.WriteLine(newProduct2);
Console.WriteLine("Saving...");
newProduct1.Save();
newProduct2.Save();
Console.ReadLine();
// as a further example of the new property usage..
if (newProduct1.UnitPrice > 5)
Console.WriteLine(newProduct1);
Console.WriteLine("Using nullable types is a great way to simplify code...");
Console.ReadLine();
}
}
}
Output
Product: Widget Price: 5.99
Product: Rare Widget Price: Out of stock
Saving...
Value written to the database: 5.99
Value written to the database:
Product: Widget Price: 5.99
Product: Rare Widget Price: Out of stock
Saving...
Value written to the database: 5.99
Value written to the database:
Product: Widget Price: 5.99
Using nullable data types is a great way to simplify code...
Let me know if there are more specific implementation details that concern you making the switch.