【问题标题】:Computing values before calling base constructor在调用基本构造函数之前计算值
【发布时间】:2017-07-30 09:55:36
【问题描述】:

有什么方法可以在后代类构造函数的末尾调用超级构造函数吗?

它在 Java 中有效,但在 C# 中,关键字 base 似乎并不等同于 Java 的 super。

例子:

class CommonChest : BasicKeyChest
{
    public CommonChest()
    {
        Random rnd = new Random();
        int key = rnd.Next(1, 6);
        int coins = rnd.Next(70, 121);
        super(key, coins, "Common");
    }
}

【问题讨论】:

  • 不,你不能延迟构造函数的执行。这是为了避免忘记调用它并确保所有继承的成员都正确初始化。
  • "它在 Java 中工作" 不,它没有。 Java要求它是第一个语句,所以和C#的base()基本一样,只是写的地方不一样。

标签: c# .net oop


【解决方案1】:

没有办法推迟对基构造函数的调用,它必须在派生构造函数启动之前完成。

但是,您可以在调用基构造函数之前在派生构造函数之外执行计算,方法是提供一个传递给基构造函数的表达式:

class CommonChest : BasicKeyChest {
    public CommonChest()
    :   this(GenTuple()) {
    }
    private CommonChest(Tuple<int,int> keysCoins)
    :   base(keysCoins.Item1, keysCoins.Item2, "Common") {
    }
    private static Tuple<int,int> GenTuple() {
        Random rnd = new Random();
        int keys = rnd.Next(1, 6);
        int coins = rnd.Next(70, 121);
        return Tuple.Create(keys, coins);
    }
}

上面有点棘手:一个带有一对整数的私有构造函数用于将这些整数转发给基本构造函数。元组在GenTuple 方法中生成,该方法在调用base 构造函数之前 被调用。

【讨论】:

  • @Rahul 是的。我希望 C# 7 能让元组的丑陋不那么明显,那么上面的片段就有机会获得一些可读性。
  • 这似乎是一种不必要的复杂方法,如果可以在最后调用构造函数,则可以解决。但是感谢这应该是在 C# 中解决这个问题的最简单方法。
【解决方案2】:

不,使用base 关键字或Constructor Initializer 的概念是首先调用基本构造函数,然后调用子构造函数。这样子类中的所有公共或共享参数首先被初始化,然后是子类的特定属性。这也是abstract 类可以有构造函数的原因之一

【讨论】:

  • 那太糟糕了... :) 所以我确实需要用 2 种方法破解该代码?
【解决方案3】:

您可以在调用基本构造函数时调用 静态 方法:

class CommonChest : BasicKeyChest
{
    public CommonChest() : base(DoSomething())
    {

    }

    private static Tuple<int,int> DoSomething()
    {
        Random rnd = new Random();
        int key = rnd.Next(1, 6);
        int coins = rnd.Next(70, 121);
        return Tuple.Create(key, coins);
    }
}

【讨论】:

    【解决方案4】:

    这种设计避免了您在派生构造函数中从基类访问成员,尽管它尚未初始化,因为它的基类构造函数未被调用。

    想象一下这是可能的:

    class MyClass
    {
        MyClass()
        {
            var a = base.MyBaseProperty;
            base();
        }
    }
    

    在调用base() 之前a 会是什么?由于myBaseProperty 在基类中声明,如果基类构造函数不是第一个语句,它将被统一化。

    此外,如果您忘记了对 base(...) 的调用,编译器会通知您,这样您就不会在不调用基类的情况下意外运行构造函数。

    【讨论】:

    • 这并不能证明什么,他们只能在基调用之前禁止访问实例字段,只有局部变量和静态。这只是Java设计缺陷。遗憾的是它甚至在 2020 年都没有修复
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-11-17
    • 1970-01-01
    • 1970-01-01
    • 2010-10-18
    • 1970-01-01
    • 2012-05-02
    相关资源
    最近更新 更多