我有一个类,它包含两个相同类型的属性。decimal NetAmount和decimal GrossAmount
我希望使用GrossAmount或NetAmount来初始化它,并根据指定的一个计算第二个。
哪条路最优雅,为什么?(为了简洁起见,省略了参数验证)
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)
};
}
}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; }
}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; }
}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; }
}从打电话者的角度看它是什么样子的:
// 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);税务展期:
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);
}
}在我的上层,我用POCOs/DTOs传递这些价格,例如:
public class PriceDTO
{
public decimal NetAmount { get; set; }
public decimal GrossAmount { get; set; }
}我也要检查一下,哪一个是通过的,决定从哪一个计算。因此,如果有一个映射,则如下所示:
if (priceDto.GrossAmount != default)
return TaxedPrice.FromGross(priceDto.GrossAmount, taxRate);
else if (priceDto.NetAmount != default)
return TaxedPrice.FromNet(priceDto.NetAmount, taxRate);
else
// error2的情况下(不需要签入映射代码)
return new TaxedPrice(priceDto.NetAmount, priceDto.GrossAmount, taxRate)3-还有支票
4-与1和3相同
我同意这可能是一个struct。
发布于 2018-10-03 13:04:21
我个人倾向于选择第一个选项,因为这是迄今为止最简单的,因为名称FromNet和FromGross清楚地表明了代码正在做什么。在其他例子中,这一点就不清楚了。
然而,仍有改进的余地。这两种方法都执行相同的基本计算,从而得到了四个近似非严格的表达式。所以干可以在这里应用:
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 = ApplyRounding(netAmount),
GrossAmount = ApplyRounding(netAmount.ApplyTax(taxRate))
};
}
public static TaxedPrice FromGross(decimal grossAmount, decimal taxRate)
{
return new TaxedPrice
{
GrossAmount = ApplyRounding(grossAmount),
NetAmount = ApplyRounding(grossAmount.RemoveTax(taxRate))
};
}
private decimal ApplyRounding(decimal rawValue)
=> decimal.Round(rawValue, 2, MidpointRounding.AwayFromZero)
}发布于 2018-10-03 14:16:33
另一个可能的选择。在您的系统中创建NetAmount和GrossAmount的头等类型,并提供implicit转换。我面临的唯一问题是如何像原来的那样指定每个调用的税率(正如您在最后的使用示例中所看到的那样,我的电话有些全局)。如果有人在这方面有一个很好的解决办法,我很想看看。您还可以添加相等/比较方法和运算符,并让它实现任意多个接口(如decimal )。
public struct NetAmount
{
private static decimal _globalTaxRate;
public NetAmount(decimal amount, decimal globalTaxRate)
{
this.Amount = decimal.Round(amount, 2, MidpointRounding.AwayFromZero);
_globalTaxRate = globalTaxRate;
}
public decimal Amount { get; }
public static decimal GlobalTaxRate => _globalTaxRate;
public static implicit operator decimal(NetAmount netAmount)
{
return netAmount.Amount;
}
public static implicit operator NetAmount(decimal amount)
{
return new NetAmount(amount, _globalTaxRate);
}
public static implicit operator GrossAmount(NetAmount netAmount)
{
return decimal.Round(netAmount.ApplyTax(_globalTaxRate), 2, MidpointRounding.AwayFromZero);
}
public override string ToString()
{
return this.Amount.ToString();
}
}public struct GrossAmount
{
private static decimal _globalTaxRate;
public GrossAmount(decimal amount, decimal globalTaxRate)
{
this.Amount = decimal.Round(amount, 2, MidpointRounding.AwayFromZero);
_globalTaxRate = globalTaxRate;
}
public decimal Amount { get; }
public static decimal GlobalTaxRate => _globalTaxRate;
public static implicit operator decimal(GrossAmount grossAmount)
{
return grossAmount.Amount;
}
public static implicit operator GrossAmount(decimal amount)
{
return new GrossAmount(amount, _globalTaxRate);
}
public static implicit operator NetAmount(GrossAmount grossAmount)
{
return decimal.Round(grossAmount.RemoveTax(_globalTaxRate), 2, MidpointRounding.AwayFromZero);
}
public override string ToString()
{
return this.Amount.ToString();
}
}public static class TaxExtensions
{
public static GrossAmount ApplyTax(this NetAmount netPrice, decimal taxRate)
{
return netPrice * (taxRate + 1);
}
public static NetAmount RemoveTax(this GrossAmount grossPrice, decimal taxRate)
{
return grossPrice / (taxRate + 1);
}
}// Only to set the global tax rate;
NetAmount init1 = new NetAmount(0.00m, 0.23m);
GrossAmount init2 = new GrossAmount(0.00m, 0.23m);
GrossAmount untaxedPrice = (NetAmount)2.13m;
NetAmount taxedPrice = (GrossAmount)2.00m;
Console.WriteLine(untaxedPrice + " " + taxedPrice);
Console.ReadLine();https://codereview.stackexchange.com/questions/204832
复制相似问题