C# "Rename"派生类中的属性

标签 c# properties alias derived-class base-class

当你读到这篇文章时,你会很想给出这样的建议,比如“这是一个坏主意,原因如下……”

请耐心等待。我知道还有其他方法可以解决这个问题。这个问题应该被认为是琐事。

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

让我们以交易“金额”为例,这是给定交易中最重要的货币金额。

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

    public TxnTypeEnum TransactionType { get; set; }
}

此金额在派生类型中可能有更具体的名称……至少在现实世界中是这样。例如,以下值实际上都是同一个东西:

  • 交易 - 金额
  • 发票 - 小计
  • 采购订单 - 总计
  • 销售收据 - 金额

所以现在我想要一个派生类“发票”,它有一个小计而不是一般命名的金额。理想情况下,以下两项都为真:

  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; }
}

当然,Transaction.Amount 在 Invoice 的任何实例上仍然可见。

感谢您的关注!

最佳答案

感谢所有的帮助。

好的,当派生类是基实例时,当然不能“隐藏”基类的公共(public)属性。在我大脑深处的某个地方,我已经知道了。呸!

我最终通过使用名为 TransactionBase 的第三类,让语法糖按照我希望的方式为消费者服务。此类是抽象的,包含存在于所有交易中的共享的、非别名的内容,例如货币、汇率、创建/修改的日期和时间、交易日期等……除了金额等别名的内容。

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

public abstract class TransactionBase
{
    protected virtual double Amount { get; set; }
}

然后交易看起来像这样:

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

和发票:

public class Invoice : TransactionBase
{
    public double SubTotal
    {
        get
        {
            return Amount;
        }
        set
        {
            Amount = value;
        }
    }
}

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

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;

所以我最初的问题的答案是,“不”你不能隐藏公共(public)继承成员。上面的解决方案通过直接访问派生类型中的 protected 成员来伪造它,但它仍然有点糟糕。打字太多。

当然,既然我摆弄了所有这些,我发现一个更好的解决方案完全抛弃了 protected 成员并节省了我一些打字时间。顺便说一下,是的,我很尴尬,我没有立即跳到这个解决方案。

编辑:实际上,我回答中的第一个方法可能更好。对于第二个,当从交易转换为发票时,我会丢失“金额”或“小计”。

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; }
}

关于C# "Rename"派生类中的属性,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12325637/

相关文章:

c# - 引用同一 DLL 的多个版本

c# - 具有公共(public)getter的抽象属性,可以在具体类中定义私有(private)setter吗?

c# - 如何在没有自定义类类型的情况下获取一个类的属性

linux - 如何在bash_profile中编写函数

c# - 在不更新 Database First Entity Framework MVC 应用程序中的其他模型的情况下向模型 (edmx) 添加新表

c# - Visual Studio 2017 - 消息筛选器指示应用程序正忙

macos - 如何在一个语句中为一个命令定义两个别名

wordpress - 如何防止EasyPHP DevServer 16为别名添加前缀 'edsa'

c# - 如何从 C# 类生成数据库表?

Ant property glob 进入全局属性空间