C#"重命名"派生类中的属性

Eri*_*ham 9 c# alias properties base-class derived-class

当你读到这篇文章时,你会非常想提出一些建议,比如"由于以下原因,这是一个坏主意......"

忍受我.我知道还有其他方法可以解决这个问题.这个问题应该被认为是琐事.

假设您有一个"交易"类,它具有所有交易的共同属性,例如发票,采购订单和销售收据.

让我们以交易"金额"的简单示例为例,这是给定交易的最重要的货币金额.

public class Transaction
{
    public double Amount { get; set; }

    public TxnTypeEnum TransactionType { get; set; }
}
Run Code Online (Sandbox Code Playgroud)

此数量可能在派生类型中具有更具体的名称...至少在现实世界中.例如,以下值实际上都是相同的:

  • 交易 - 金额
  • 发票 - 小计
  • PurchaseOrder - 总计
  • 销售收据 - 金额

所以现在我想要一个派生类"Invoice",它有一个小计而不是一般命名的Amount.理想情况下,以下两种情况都是正确的:

  1. 在Transaction的实例中,Amount属性将是可见的.
  2. 在Invoice的实例中,Amount属性将被隐藏,但Subtotal属性将在内部引用它.

发票看起来像这样:

public class Invoice : Transaction
{
    new private double? Amount
    {
        get
        {
            return base.Amount;
        }
        set
        {
            base.Amount = value;
        }
    }

    // This property should hide the generic property "Amount" on Transaction
    public double? SubTotal
    {
        get
        {
            return Amount;
        }
        set
        {
            Amount = value;
        }
    }

    public double RemainingBalance { get; set; }
}
Run Code Online (Sandbox Code Playgroud)

但当然,在任何Invoice实例上仍然可以看到Transaction.Amount.

谢谢参观!

Eri*_*ham 6

谢谢你的帮助.

好吧,当派生类是基础实例时,当然不能"隐藏"基类上的公共属性.在我脑海深处的某个地方,我已经知道了.卫生署!

通过使用名为TransactionBase的第三个类,我最终得到了语法糖,以表达我对消费者的想法.这个类是抽象的,包含所有交易的共享,非别名的东西,如货币,汇率,创建/修改日期和时间,交易日期等......除了Amount这样的别名之外.

在这里,我只显示有问题的Amount属性:

public abstract class TransactionBase
{
    protected virtual double Amount { get; set; }
}
Run Code Online (Sandbox Code Playgroud)

然后Transaction看起来像这样:

public class Transaction : TransactionBase
{
    public new double Amount 
    { 
        get
        {
            return base.Amount;
        }
        set
        {
            base.Amount = value;
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

和发票:

public class Invoice : TransactionBase
{
    public double SubTotal
    {
        get
        {
            return Amount;
        }
        set
        {
            Amount = value;
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

访问按照我想要的方式工作:

var transaction = new Transaction();

// This line works fine:
var transactionAmount = transaction.Amount;



var invoice = new Invoice();

// This line works fine:
var invoiceSubtotal = invoice.SubTotal;

// This line won't compile.
// Error: TransactionBase.Amount is inaccessible due to its protection level.
var invoiceAmount = invoice.Amount;
Run Code Online (Sandbox Code Playgroud)

所以我原来的问题的答案是,"不"你不能隐藏公共继承成员.上面的解决方案通过直接在派生类型中访问受保护的成员来伪造它,但它仍然很糟糕.打字太多了.

当然,现在我摆弄和摆弄所有这些,我看到一个更好的解决方案完全抛弃了受保护的成员并节省了一些打字.顺便说一句,是的,我很尴尬,我没有立即跳到这个解决方案.

编辑:实际上,我的答案中的第一个appraoch可能会更好.对于第二个,当从交易转换为发票时,我将失去"金额"或"小计".

public abstract class TransactionBase
{
    // There are some shared properties here.
}

public class Transaction : TransactionBase
{
    public double Amount { get; set; }
}

public class Invoice : TransactionBase
{
    public double SubTotal { get; set; }
}
Run Code Online (Sandbox Code Playgroud)