首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >可逆税收计算器类

可逆税收计算器类
EN

Code Review用户
提问于 2018-10-03 07:53:39
回答 2查看 1.1K关注 0票数 7

我有一个类,它包含两个相同类型的属性。decimal NetAmountdecimal GrossAmount

我希望使用GrossAmountNetAmount来初始化它,并根据指定的一个计算第二个。

哪条路最优雅,为什么?(为了简洁起见,省略了参数验证)

1

代码语言:javascript
复制
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

代码语言:javascript
复制
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

代码语言:javascript
复制
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

代码语言:javascript
复制
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; }
}

从打电话者的角度看它是什么样子的:

代码语言:javascript
复制
// 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);

税务展期:

代码语言:javascript
复制
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传递这些价格,例如:

代码语言:javascript
复制
public class PriceDTO
{
    public decimal NetAmount { get; set; }
    public decimal GrossAmount { get; set; }
}

我也要检查一下,哪一个是通过的,决定从哪一个计算。因此,如果有一个映射,则如下所示:

代码语言:javascript
复制
if (priceDto.GrossAmount != default)
    return TaxedPrice.FromGross(priceDto.GrossAmount, taxRate);
else if (priceDto.NetAmount != default)
    return TaxedPrice.FromNet(priceDto.NetAmount, taxRate);
else
    // error

2的情况下(不需要签入映射代码)

代码语言:javascript
复制
return new TaxedPrice(priceDto.NetAmount, priceDto.GrossAmount, taxRate)

3-还有支票

4-与1和3相同

我同意这可能是一个struct

EN

回答 2

Code Review用户

回答已采纳

发布于 2018-10-03 13:04:21

我个人倾向于选择第一个选项,因为这是迄今为止最简单的,因为名称FromNetFromGross清楚地表明了代码正在做什么。在其他例子中,这一点就不清楚了。

然而,仍有改进的余地。这两种方法都执行相同的基本计算,从而得到了四个近似非严格的表达式。所以干可以在这里应用:

代码语言:javascript
复制
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)

}
票数 4
EN

Code Review用户

发布于 2018-10-03 14:16:33

另一个可能的选择。在您的系统中创建NetAmountGrossAmount的头等类型,并提供implicit转换。我面临的唯一问题是如何像原来的那样指定每个调用的税率(正如您在最后的使用示例中所看到的那样,我的电话有些全局)。如果有人在这方面有一个很好的解决办法,我很想看看。您还可以添加相等/比较方法和运算符,并让它实现任意多个接口(如decimal )。

NetAmount.cs

代码语言:javascript
复制
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();
    }
}

GrossAmount.cs

代码语言:javascript
复制
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();
    }
}

TaxExtensions.cs

代码语言:javascript
复制
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);
    }
}

使用

代码语言:javascript
复制
// 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();
票数 2
EN
页面原文内容由Code Review提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://codereview.stackexchange.com/questions/204832

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档