Say you have a Price object that accepts either an (int quantity, decimal price) or a string containing “4/$3.99”. Is there a way to limit which properties can be set together? Feel free to correct me in my logic below.
The Test: A and B are equal to each other, but the C example should not be allowed. Thus the question How to enforce that all three parameters are not invoked as in the C example?
AdPrice A = new AdPrice { priceText = "4/$3.99"}; // Valid
AdPrice B = new AdPrice { qty = 4, price = 3.99m}; // Valid
AdPrice C = new AdPrice { qty = 4, priceText = "2/$1.99", price = 3.99m};// Not
The class:
public class AdPrice {
private int _qty;
private decimal _price;
private string _priceText;
The constructors:
public AdPrice () : this( qty: 0, price: 0.0m) {} // Default Constructor
public AdPrice (int qty = 0, decimal price = 0.0m) { // Numbers only
this.qty = qty;
this.price = price; }
public AdPrice (string priceText = "0/$0.00") { // String only
this.priceText = priceText; }
The Methods:
private void SetPriceValues() {
var matches = Regex.Match(_priceText,
@"^\s?((?<qty>\d+)\s?/)?\s?[$]?\s?(?<price>[0-9]?\.?[0-9]?[0-9]?)");
if( matches.Success) {
if (!Decimal.TryParse(matches.Groups["price"].Value,
out this._price))
this._price = 0.0m;
if (!Int32.TryParse(matches.Groups["qty"].Value,
out this._qty))
this._qty = (this._price > 0 ? 1 : 0);
else
if (this._price > 0 && this._qty == 0)
this._qty = 1;
} }
private void SetPriceString() {
this._priceText = (this._qty > 1 ?
this._qty.ToString() + '/' : "") +
String.Format("{0:C}",this.price);
}
The Accessors:
public int qty {
get { return this._qty; }
set { this._qty = value; this.SetPriceString(); } }
public decimal price {
get { return this._price; }
set { this._price = value; this.SetPriceString(); } }
public string priceText {
get { return this._priceText; }
set { this._priceText = value; this.SetPriceValues(); } }
}
If you are just going to be able to assign values directly to the properties as you are doing and have a default constructor why bother with constructors at all?
If the
priceTextandprice/qtyboth need to be mutable externally then under what conditions would you consider object initialization to be complete:-The above is the same code as you are using just without the “syntatic sugar”. In order to prevent your example from occuring you would need to be able to prevent the above.
My suggestion would be to make the
priceTextproperty private. To initialise the object using a string one would be required to use the appropriate constructor.