Elegant way to initialize from one of two values of the same type
Clash Royale CLAN TAG#URR8PPP
up vote
1
down vote
favorite
I have a class that contains 2 properties of the same type. decimal NetAmount
and decimal GrossAmount
I would like to initialize it using either GrossAmount
or NetAmount
and based on the one specified calculate the second one.
Which way is the most elegant and why? (parameter validation is omitted for brevity)
1
public class TaxedPrice
private TaxedPrice()
public decimal NetAmount get; private set;
public decimal GrossAmount get; private set;
public static TaxedPrice FromNet(decimal netAmount, decimal taxRate)
return new TaxedPrice
NetAmount = decimal.Round(netAmount, 2, MidpointRounding.AwayFromZero),
GrossAmount = decimal.Round(netAmount.ApplyTax(taxRate), 2, MidpointRounding.AwayFromZero)
;
public static TaxedPrice FromGross(decimal grossAmount, decimal taxRate)
return new TaxedPrice
GrossAmount = decimal.Round(grossAmount, 2, MidpointRounding.AwayFromZero),
NetAmount = decimal.Round(grossAmount.RemoveTax(taxRate), 2, MidpointRounding.AwayFromZero)
;
2
public class TaxedPrice
public TaxedPrice(decimal netAmount, decimal grossAmount, decimal taxRate)
if (grossAmount != default)
GrossAmount = decimal.Round(grossAmount, 2, MidpointRounding.AwayFromZero);
NetAmount = decimal.Round(grossAmount.RemoveTax(taxRate), 2, MidpointRounding.AwayFromZero);
else if (netAmount != default)
NetAmount = decimal.Round(netAmount, 2, MidpointRounding.AwayFromZero);
GrossAmount = decimal.Round(netAmount.ApplyTax(taxRate), 2, MidpointRounding.AwayFromZero);
else
throw new InvalidOperationException($"Either nameof(netAmount) or grossAmount must be set.");
public decimal NetAmount get;
public decimal GrossAmount get;
3
public class TaxedPrice
public enum Type
Gross,
Net
public TaxedPrice(decimal amount, Type type, decimal taxRate)
if (type == Type.Gross)
GrossAmount = decimal.Round(amount, 2, MidpointRounding.AwayFromZero);
NetAmount = decimal.Round(amount.RemoveTax(taxRate), 2, MidpointRounding.AwayFromZero);
else if (type == Type.Net)
NetAmount = decimal.Round(amount, 2, MidpointRounding.AwayFromZero);
GrossAmount = decimal.Round(amount.ApplyTax(taxRate), 2, MidpointRounding.AwayFromZero);
public decimal NetAmount get;
public decimal GrossAmount get;
4
public class TaxedPrice
public TaxedPrice(decimal amount, bool fromGross, decimal taxRate)
if (fromGross)
GrossAmount = decimal.Round(amount, 2, MidpointRounding.AwayFromZero);
NetAmount = decimal.Round(amount.RemoveTax(taxRate), 2, MidpointRounding.AwayFromZero);
else
NetAmount = decimal.Round(amount, 2, MidpointRounding.AwayFromZero);
GrossAmount = decimal.Round(amount.ApplyTax(taxRate), 2, MidpointRounding.AwayFromZero);
public decimal NetAmount get;
public decimal GrossAmount get;
How it looks like from caller's side:
// 1
var taxedPrice = TaxedPrice.FromNet(2.123m, 0.23m);
// 2
var taxedPrice = new TaxedPrice(2.123m, default, 0.23m); // uses the first one to calculate the second one
var taxedPrice2 = new TaxedPrice(2.123m, 1.11m, 0.23m); // uses the first one to calculate the second one
var taxedPrice3 = new TaxedPrice(default, 1.11m, 0.23m); // uses the second one to calculate the first one
// 3
var taxedPrice = new TaxedPrice(2.123m, TaxedPrice.Type.Net, 0.23m);
// 4
var taxedPrice = new TaxedPrice(2.123m, false, 0.23m);
Extensions for tax:
public static class TaxExtensions
public static decimal ApplyTax(this decimal netPrice, decimal taxRate)
return netPrice * (taxRate + 1);
public static decimal RemoveTax(this decimal grossPrice, decimal taxRate)
return grossPrice / (taxRate + 1);
In my upper layer I pass those prices in POCOs/DTOs like:
public class PriceDTO
public decimal NetAmount get; set;
public decimal GrossAmount get; set;
And I have to check there as well which one was passed to decide from which to calculate.
c# comparative-review finance
add a comment |Â
up vote
1
down vote
favorite
I have a class that contains 2 properties of the same type. decimal NetAmount
and decimal GrossAmount
I would like to initialize it using either GrossAmount
or NetAmount
and based on the one specified calculate the second one.
Which way is the most elegant and why? (parameter validation is omitted for brevity)
1
public class TaxedPrice
private TaxedPrice()
public decimal NetAmount get; private set;
public decimal GrossAmount get; private set;
public static TaxedPrice FromNet(decimal netAmount, decimal taxRate)
return new TaxedPrice
NetAmount = decimal.Round(netAmount, 2, MidpointRounding.AwayFromZero),
GrossAmount = decimal.Round(netAmount.ApplyTax(taxRate), 2, MidpointRounding.AwayFromZero)
;
public static TaxedPrice FromGross(decimal grossAmount, decimal taxRate)
return new TaxedPrice
GrossAmount = decimal.Round(grossAmount, 2, MidpointRounding.AwayFromZero),
NetAmount = decimal.Round(grossAmount.RemoveTax(taxRate), 2, MidpointRounding.AwayFromZero)
;
2
public class TaxedPrice
public TaxedPrice(decimal netAmount, decimal grossAmount, decimal taxRate)
if (grossAmount != default)
GrossAmount = decimal.Round(grossAmount, 2, MidpointRounding.AwayFromZero);
NetAmount = decimal.Round(grossAmount.RemoveTax(taxRate), 2, MidpointRounding.AwayFromZero);
else if (netAmount != default)
NetAmount = decimal.Round(netAmount, 2, MidpointRounding.AwayFromZero);
GrossAmount = decimal.Round(netAmount.ApplyTax(taxRate), 2, MidpointRounding.AwayFromZero);
else
throw new InvalidOperationException($"Either nameof(netAmount) or grossAmount must be set.");
public decimal NetAmount get;
public decimal GrossAmount get;
3
public class TaxedPrice
public enum Type
Gross,
Net
public TaxedPrice(decimal amount, Type type, decimal taxRate)
if (type == Type.Gross)
GrossAmount = decimal.Round(amount, 2, MidpointRounding.AwayFromZero);
NetAmount = decimal.Round(amount.RemoveTax(taxRate), 2, MidpointRounding.AwayFromZero);
else if (type == Type.Net)
NetAmount = decimal.Round(amount, 2, MidpointRounding.AwayFromZero);
GrossAmount = decimal.Round(amount.ApplyTax(taxRate), 2, MidpointRounding.AwayFromZero);
public decimal NetAmount get;
public decimal GrossAmount get;
4
public class TaxedPrice
public TaxedPrice(decimal amount, bool fromGross, decimal taxRate)
if (fromGross)
GrossAmount = decimal.Round(amount, 2, MidpointRounding.AwayFromZero);
NetAmount = decimal.Round(amount.RemoveTax(taxRate), 2, MidpointRounding.AwayFromZero);
else
NetAmount = decimal.Round(amount, 2, MidpointRounding.AwayFromZero);
GrossAmount = decimal.Round(amount.ApplyTax(taxRate), 2, MidpointRounding.AwayFromZero);
public decimal NetAmount get;
public decimal GrossAmount get;
How it looks like from caller's side:
// 1
var taxedPrice = TaxedPrice.FromNet(2.123m, 0.23m);
// 2
var taxedPrice = new TaxedPrice(2.123m, default, 0.23m); // uses the first one to calculate the second one
var taxedPrice2 = new TaxedPrice(2.123m, 1.11m, 0.23m); // uses the first one to calculate the second one
var taxedPrice3 = new TaxedPrice(default, 1.11m, 0.23m); // uses the second one to calculate the first one
// 3
var taxedPrice = new TaxedPrice(2.123m, TaxedPrice.Type.Net, 0.23m);
// 4
var taxedPrice = new TaxedPrice(2.123m, false, 0.23m);
Extensions for tax:
public static class TaxExtensions
public static decimal ApplyTax(this decimal netPrice, decimal taxRate)
return netPrice * (taxRate + 1);
public static decimal RemoveTax(this decimal grossPrice, decimal taxRate)
return grossPrice / (taxRate + 1);
In my upper layer I pass those prices in POCOs/DTOs like:
public class PriceDTO
public decimal NetAmount get; set;
public decimal GrossAmount get; set;
And I have to check there as well which one was passed to decide from which to calculate.
c# comparative-review finance
There are some methods missing:RemoveTax
andApplyTax
. Are these methods extensions?
– t3chb0t
1 hour ago
@t3chb0t simple extensions fordecimal
type that add/remove tax from the price.
– Konrad
1 hour ago
ok, it'd be great if you could add them too so that people can copy/paste your code into an IDE and test it if they like ;-)
– t3chb0t
59 mins ago
1
@t3chb0t added code
– Konrad
56 mins ago
oh, there is one more thing... since you have posted four versions of theTaxedPrice
class, it would be very helpful for reviewers if you summarized what are the differences between each version.
– t3chb0t
52 mins ago
add a comment |Â
up vote
1
down vote
favorite
up vote
1
down vote
favorite
I have a class that contains 2 properties of the same type. decimal NetAmount
and decimal GrossAmount
I would like to initialize it using either GrossAmount
or NetAmount
and based on the one specified calculate the second one.
Which way is the most elegant and why? (parameter validation is omitted for brevity)
1
public class TaxedPrice
private TaxedPrice()
public decimal NetAmount get; private set;
public decimal GrossAmount get; private set;
public static TaxedPrice FromNet(decimal netAmount, decimal taxRate)
return new TaxedPrice
NetAmount = decimal.Round(netAmount, 2, MidpointRounding.AwayFromZero),
GrossAmount = decimal.Round(netAmount.ApplyTax(taxRate), 2, MidpointRounding.AwayFromZero)
;
public static TaxedPrice FromGross(decimal grossAmount, decimal taxRate)
return new TaxedPrice
GrossAmount = decimal.Round(grossAmount, 2, MidpointRounding.AwayFromZero),
NetAmount = decimal.Round(grossAmount.RemoveTax(taxRate), 2, MidpointRounding.AwayFromZero)
;
2
public class TaxedPrice
public TaxedPrice(decimal netAmount, decimal grossAmount, decimal taxRate)
if (grossAmount != default)
GrossAmount = decimal.Round(grossAmount, 2, MidpointRounding.AwayFromZero);
NetAmount = decimal.Round(grossAmount.RemoveTax(taxRate), 2, MidpointRounding.AwayFromZero);
else if (netAmount != default)
NetAmount = decimal.Round(netAmount, 2, MidpointRounding.AwayFromZero);
GrossAmount = decimal.Round(netAmount.ApplyTax(taxRate), 2, MidpointRounding.AwayFromZero);
else
throw new InvalidOperationException($"Either nameof(netAmount) or grossAmount must be set.");
public decimal NetAmount get;
public decimal GrossAmount get;
3
public class TaxedPrice
public enum Type
Gross,
Net
public TaxedPrice(decimal amount, Type type, decimal taxRate)
if (type == Type.Gross)
GrossAmount = decimal.Round(amount, 2, MidpointRounding.AwayFromZero);
NetAmount = decimal.Round(amount.RemoveTax(taxRate), 2, MidpointRounding.AwayFromZero);
else if (type == Type.Net)
NetAmount = decimal.Round(amount, 2, MidpointRounding.AwayFromZero);
GrossAmount = decimal.Round(amount.ApplyTax(taxRate), 2, MidpointRounding.AwayFromZero);
public decimal NetAmount get;
public decimal GrossAmount get;
4
public class TaxedPrice
public TaxedPrice(decimal amount, bool fromGross, decimal taxRate)
if (fromGross)
GrossAmount = decimal.Round(amount, 2, MidpointRounding.AwayFromZero);
NetAmount = decimal.Round(amount.RemoveTax(taxRate), 2, MidpointRounding.AwayFromZero);
else
NetAmount = decimal.Round(amount, 2, MidpointRounding.AwayFromZero);
GrossAmount = decimal.Round(amount.ApplyTax(taxRate), 2, MidpointRounding.AwayFromZero);
public decimal NetAmount get;
public decimal GrossAmount get;
How it looks like from caller's side:
// 1
var taxedPrice = TaxedPrice.FromNet(2.123m, 0.23m);
// 2
var taxedPrice = new TaxedPrice(2.123m, default, 0.23m); // uses the first one to calculate the second one
var taxedPrice2 = new TaxedPrice(2.123m, 1.11m, 0.23m); // uses the first one to calculate the second one
var taxedPrice3 = new TaxedPrice(default, 1.11m, 0.23m); // uses the second one to calculate the first one
// 3
var taxedPrice = new TaxedPrice(2.123m, TaxedPrice.Type.Net, 0.23m);
// 4
var taxedPrice = new TaxedPrice(2.123m, false, 0.23m);
Extensions for tax:
public static class TaxExtensions
public static decimal ApplyTax(this decimal netPrice, decimal taxRate)
return netPrice * (taxRate + 1);
public static decimal RemoveTax(this decimal grossPrice, decimal taxRate)
return grossPrice / (taxRate + 1);
In my upper layer I pass those prices in POCOs/DTOs like:
public class PriceDTO
public decimal NetAmount get; set;
public decimal GrossAmount get; set;
And I have to check there as well which one was passed to decide from which to calculate.
c# comparative-review finance
I have a class that contains 2 properties of the same type. decimal NetAmount
and decimal GrossAmount
I would like to initialize it using either GrossAmount
or NetAmount
and based on the one specified calculate the second one.
Which way is the most elegant and why? (parameter validation is omitted for brevity)
1
public class TaxedPrice
private TaxedPrice()
public decimal NetAmount get; private set;
public decimal GrossAmount get; private set;
public static TaxedPrice FromNet(decimal netAmount, decimal taxRate)
return new TaxedPrice
NetAmount = decimal.Round(netAmount, 2, MidpointRounding.AwayFromZero),
GrossAmount = decimal.Round(netAmount.ApplyTax(taxRate), 2, MidpointRounding.AwayFromZero)
;
public static TaxedPrice FromGross(decimal grossAmount, decimal taxRate)
return new TaxedPrice
GrossAmount = decimal.Round(grossAmount, 2, MidpointRounding.AwayFromZero),
NetAmount = decimal.Round(grossAmount.RemoveTax(taxRate), 2, MidpointRounding.AwayFromZero)
;
2
public class TaxedPrice
public TaxedPrice(decimal netAmount, decimal grossAmount, decimal taxRate)
if (grossAmount != default)
GrossAmount = decimal.Round(grossAmount, 2, MidpointRounding.AwayFromZero);
NetAmount = decimal.Round(grossAmount.RemoveTax(taxRate), 2, MidpointRounding.AwayFromZero);
else if (netAmount != default)
NetAmount = decimal.Round(netAmount, 2, MidpointRounding.AwayFromZero);
GrossAmount = decimal.Round(netAmount.ApplyTax(taxRate), 2, MidpointRounding.AwayFromZero);
else
throw new InvalidOperationException($"Either nameof(netAmount) or grossAmount must be set.");
public decimal NetAmount get;
public decimal GrossAmount get;
3
public class TaxedPrice
public enum Type
Gross,
Net
public TaxedPrice(decimal amount, Type type, decimal taxRate)
if (type == Type.Gross)
GrossAmount = decimal.Round(amount, 2, MidpointRounding.AwayFromZero);
NetAmount = decimal.Round(amount.RemoveTax(taxRate), 2, MidpointRounding.AwayFromZero);
else if (type == Type.Net)
NetAmount = decimal.Round(amount, 2, MidpointRounding.AwayFromZero);
GrossAmount = decimal.Round(amount.ApplyTax(taxRate), 2, MidpointRounding.AwayFromZero);
public decimal NetAmount get;
public decimal GrossAmount get;
4
public class TaxedPrice
public TaxedPrice(decimal amount, bool fromGross, decimal taxRate)
if (fromGross)
GrossAmount = decimal.Round(amount, 2, MidpointRounding.AwayFromZero);
NetAmount = decimal.Round(amount.RemoveTax(taxRate), 2, MidpointRounding.AwayFromZero);
else
NetAmount = decimal.Round(amount, 2, MidpointRounding.AwayFromZero);
GrossAmount = decimal.Round(amount.ApplyTax(taxRate), 2, MidpointRounding.AwayFromZero);
public decimal NetAmount get;
public decimal GrossAmount get;
How it looks like from caller's side:
// 1
var taxedPrice = TaxedPrice.FromNet(2.123m, 0.23m);
// 2
var taxedPrice = new TaxedPrice(2.123m, default, 0.23m); // uses the first one to calculate the second one
var taxedPrice2 = new TaxedPrice(2.123m, 1.11m, 0.23m); // uses the first one to calculate the second one
var taxedPrice3 = new TaxedPrice(default, 1.11m, 0.23m); // uses the second one to calculate the first one
// 3
var taxedPrice = new TaxedPrice(2.123m, TaxedPrice.Type.Net, 0.23m);
// 4
var taxedPrice = new TaxedPrice(2.123m, false, 0.23m);
Extensions for tax:
public static class TaxExtensions
public static decimal ApplyTax(this decimal netPrice, decimal taxRate)
return netPrice * (taxRate + 1);
public static decimal RemoveTax(this decimal grossPrice, decimal taxRate)
return grossPrice / (taxRate + 1);
In my upper layer I pass those prices in POCOs/DTOs like:
public class PriceDTO
public decimal NetAmount get; set;
public decimal GrossAmount get; set;
And I have to check there as well which one was passed to decide from which to calculate.
c# comparative-review finance
c# comparative-review finance
edited 30 mins ago
asked 1 hour ago


Konrad
1236
1236
There are some methods missing:RemoveTax
andApplyTax
. Are these methods extensions?
– t3chb0t
1 hour ago
@t3chb0t simple extensions fordecimal
type that add/remove tax from the price.
– Konrad
1 hour ago
ok, it'd be great if you could add them too so that people can copy/paste your code into an IDE and test it if they like ;-)
– t3chb0t
59 mins ago
1
@t3chb0t added code
– Konrad
56 mins ago
oh, there is one more thing... since you have posted four versions of theTaxedPrice
class, it would be very helpful for reviewers if you summarized what are the differences between each version.
– t3chb0t
52 mins ago
add a comment |Â
There are some methods missing:RemoveTax
andApplyTax
. Are these methods extensions?
– t3chb0t
1 hour ago
@t3chb0t simple extensions fordecimal
type that add/remove tax from the price.
– Konrad
1 hour ago
ok, it'd be great if you could add them too so that people can copy/paste your code into an IDE and test it if they like ;-)
– t3chb0t
59 mins ago
1
@t3chb0t added code
– Konrad
56 mins ago
oh, there is one more thing... since you have posted four versions of theTaxedPrice
class, it would be very helpful for reviewers if you summarized what are the differences between each version.
– t3chb0t
52 mins ago
There are some methods missing:
RemoveTax
and ApplyTax
. Are these methods extensions?– t3chb0t
1 hour ago
There are some methods missing:
RemoveTax
and ApplyTax
. Are these methods extensions?– t3chb0t
1 hour ago
@t3chb0t simple extensions for
decimal
type that add/remove tax from the price.– Konrad
1 hour ago
@t3chb0t simple extensions for
decimal
type that add/remove tax from the price.– Konrad
1 hour ago
ok, it'd be great if you could add them too so that people can copy/paste your code into an IDE and test it if they like ;-)
– t3chb0t
59 mins ago
ok, it'd be great if you could add them too so that people can copy/paste your code into an IDE and test it if they like ;-)
– t3chb0t
59 mins ago
1
1
@t3chb0t added code
– Konrad
56 mins ago
@t3chb0t added code
– Konrad
56 mins ago
oh, there is one more thing... since you have posted four versions of the
TaxedPrice
class, it would be very helpful for reviewers if you summarized what are the differences between each version.– t3chb0t
52 mins ago
oh, there is one more thing... since you have posted four versions of the
TaxedPrice
class, it would be very helpful for reviewers if you summarized what are the differences between each version.– t3chb0t
52 mins ago
add a comment |Â
1 Answer
1
active
oldest
votes
up vote
2
down vote
In my opinion, you should go for number 1 (with one small change).
Reasons for choosing this one:
- Easy to modify - you can add new
FromX
method - Clear - it states exactly what do you calculate
- Doesn't require explanation beforehand to do some checking by consumer (as in number 2)
Drawback:
(big one) It might disrupt testing, mocking a static method is a nightmare (unless you can afford moles).
Taking this all into account, I'd do a little bit of overengeneering and create a factory(-ish) class to build you a TaxedPrice object. For example:
public class TaxedPriceFactory: ITaxedPriceFactory
public TaxedPrice CreateFromNet(decimal netAmount, decimal taxRate)
//body
public TaxedPrice CreateFromGross(decimal grossAmount, decimal taxRate)
// body
This should have all three of advantages I mentioned earlier and it is easy to use in tests now.
Addendum:
Consider making your TaxedPrice
a immutable struct instead of a class with two read-only properties.
EDIT: class and method names changed as suggested by @t3chb0t
1
I don't think this is overengineered. If you named itTaxedPriceFactory
andCreateFromNet
it'd be exactly as books suggest it ;-)
– t3chb0t
19 mins ago
add a comment |Â
1 Answer
1
active
oldest
votes
1 Answer
1
active
oldest
votes
active
oldest
votes
active
oldest
votes
up vote
2
down vote
In my opinion, you should go for number 1 (with one small change).
Reasons for choosing this one:
- Easy to modify - you can add new
FromX
method - Clear - it states exactly what do you calculate
- Doesn't require explanation beforehand to do some checking by consumer (as in number 2)
Drawback:
(big one) It might disrupt testing, mocking a static method is a nightmare (unless you can afford moles).
Taking this all into account, I'd do a little bit of overengeneering and create a factory(-ish) class to build you a TaxedPrice object. For example:
public class TaxedPriceFactory: ITaxedPriceFactory
public TaxedPrice CreateFromNet(decimal netAmount, decimal taxRate)
//body
public TaxedPrice CreateFromGross(decimal grossAmount, decimal taxRate)
// body
This should have all three of advantages I mentioned earlier and it is easy to use in tests now.
Addendum:
Consider making your TaxedPrice
a immutable struct instead of a class with two read-only properties.
EDIT: class and method names changed as suggested by @t3chb0t
1
I don't think this is overengineered. If you named itTaxedPriceFactory
andCreateFromNet
it'd be exactly as books suggest it ;-)
– t3chb0t
19 mins ago
add a comment |Â
up vote
2
down vote
In my opinion, you should go for number 1 (with one small change).
Reasons for choosing this one:
- Easy to modify - you can add new
FromX
method - Clear - it states exactly what do you calculate
- Doesn't require explanation beforehand to do some checking by consumer (as in number 2)
Drawback:
(big one) It might disrupt testing, mocking a static method is a nightmare (unless you can afford moles).
Taking this all into account, I'd do a little bit of overengeneering and create a factory(-ish) class to build you a TaxedPrice object. For example:
public class TaxedPriceFactory: ITaxedPriceFactory
public TaxedPrice CreateFromNet(decimal netAmount, decimal taxRate)
//body
public TaxedPrice CreateFromGross(decimal grossAmount, decimal taxRate)
// body
This should have all three of advantages I mentioned earlier and it is easy to use in tests now.
Addendum:
Consider making your TaxedPrice
a immutable struct instead of a class with two read-only properties.
EDIT: class and method names changed as suggested by @t3chb0t
1
I don't think this is overengineered. If you named itTaxedPriceFactory
andCreateFromNet
it'd be exactly as books suggest it ;-)
– t3chb0t
19 mins ago
add a comment |Â
up vote
2
down vote
up vote
2
down vote
In my opinion, you should go for number 1 (with one small change).
Reasons for choosing this one:
- Easy to modify - you can add new
FromX
method - Clear - it states exactly what do you calculate
- Doesn't require explanation beforehand to do some checking by consumer (as in number 2)
Drawback:
(big one) It might disrupt testing, mocking a static method is a nightmare (unless you can afford moles).
Taking this all into account, I'd do a little bit of overengeneering and create a factory(-ish) class to build you a TaxedPrice object. For example:
public class TaxedPriceFactory: ITaxedPriceFactory
public TaxedPrice CreateFromNet(decimal netAmount, decimal taxRate)
//body
public TaxedPrice CreateFromGross(decimal grossAmount, decimal taxRate)
// body
This should have all three of advantages I mentioned earlier and it is easy to use in tests now.
Addendum:
Consider making your TaxedPrice
a immutable struct instead of a class with two read-only properties.
EDIT: class and method names changed as suggested by @t3chb0t
In my opinion, you should go for number 1 (with one small change).
Reasons for choosing this one:
- Easy to modify - you can add new
FromX
method - Clear - it states exactly what do you calculate
- Doesn't require explanation beforehand to do some checking by consumer (as in number 2)
Drawback:
(big one) It might disrupt testing, mocking a static method is a nightmare (unless you can afford moles).
Taking this all into account, I'd do a little bit of overengeneering and create a factory(-ish) class to build you a TaxedPrice object. For example:
public class TaxedPriceFactory: ITaxedPriceFactory
public TaxedPrice CreateFromNet(decimal netAmount, decimal taxRate)
//body
public TaxedPrice CreateFromGross(decimal grossAmount, decimal taxRate)
// body
This should have all three of advantages I mentioned earlier and it is easy to use in tests now.
Addendum:
Consider making your TaxedPrice
a immutable struct instead of a class with two read-only properties.
EDIT: class and method names changed as suggested by @t3chb0t
edited 17 mins ago
answered 31 mins ago
MaLiN2223
57719
57719
1
I don't think this is overengineered. If you named itTaxedPriceFactory
andCreateFromNet
it'd be exactly as books suggest it ;-)
– t3chb0t
19 mins ago
add a comment |Â
1
I don't think this is overengineered. If you named itTaxedPriceFactory
andCreateFromNet
it'd be exactly as books suggest it ;-)
– t3chb0t
19 mins ago
1
1
I don't think this is overengineered. If you named it
TaxedPriceFactory
and CreateFromNet
it'd be exactly as books suggest it ;-)– t3chb0t
19 mins ago
I don't think this is overengineered. If you named it
TaxedPriceFactory
and CreateFromNet
it'd be exactly as books suggest it ;-)– t3chb0t
19 mins ago
add a comment |Â
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f204832%2felegant-way-to-initialize-from-one-of-two-values-of-the-same-type%23new-answer', 'question_page');
);
Post as a guest
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
There are some methods missing:
RemoveTax
andApplyTax
. Are these methods extensions?– t3chb0t
1 hour ago
@t3chb0t simple extensions for
decimal
type that add/remove tax from the price.– Konrad
1 hour ago
ok, it'd be great if you could add them too so that people can copy/paste your code into an IDE and test it if they like ;-)
– t3chb0t
59 mins ago
1
@t3chb0t added code
– Konrad
56 mins ago
oh, there is one more thing... since you have posted four versions of the
TaxedPrice
class, it would be very helpful for reviewers if you summarized what are the differences between each version.– t3chb0t
52 mins ago