是从另一个类继承的类的构造函数,效果较差

本文关键字:构造函数 继承 另一个 | 更新日期: 2023-09-27 17:52:42

问题

在我的应用程序中,我创建了大量的"小"类实例,这些实例只包含一些数据。

我知道创建类(即构造函数调用(的成本很高。我的问题是:如果我让这个小类从另一个类继承,成本会更高吗?有些字段会移动到超类,所以基本上我可以使用

注意:此问题专门针对中的性能。NET


示例情况和问题演示

考虑这两种情况:

1.case只包含一个类。它是原始类:

public class ShapeWithOffset{
    public double XOffset { get; private set; }
    public double YOffset { get; private set; }
    public IShape Shape{ get; private set; }
    public ShapeWithOffset(double xOffset, double yOffset, IShape shape){
        //check if arguments are correct/throw ArgumentException if not
        XOffset = xOffset;
        YOffset = yOffset;
        Shape = shape;
    }
    //equality members
}

2.case由两个类组成,其中第二个类继承第一个类。第二类ShapeWithHorizontalAndVerticalOffset提供与1中的ShapeWithOffset相同的功能。案例

public class ShapeWithHorizontalOffset{
    public double XOffset { get; private set; }
    public IShape Shape { get; private set; }
    public ShapeWithHorizontalOffset(double xOffset, IShape shape){
        //check if arguments are correct/throw ArgumentException if not
        XOffset = xOffset;
        Shape = shape;
    }
    //equality members
}
public class ShapeWithHorizontalAndVerticalOffset : ShapeWithHorizontalOffset{
    public double YOffset { get; private set; }
    public ShapeWithHorizontalAndVerticalOffset(double xOffset, double yOffset, 
                                                IShape shape) : base(xOffset, shape){
        //check if yOffset is correct/throw ArgumentOutOfRangeException if not
        Yffset = yOffset;
    }
    //equality members
}

我的问题是:命令var foo = new ShapeWithOffset(20, 10, shape);
快吗var boo = new ShapeWithHorizontalAndVerticalOffset(20, 10, shape);

如果我用组合而不是继承,那就是……但是继承呢?

是从另一个类继承的类的构造函数,效果较差

这闻起来像是过早优化

问题中的关键词是"…我认为…"。如果你知道自己有性能问题,那么就找出瓶颈并进行优化。如果你预计会出现性能问题,不要!以您建议的方式使用继承不太可能导致任何性能瓶颈。但是,如果你真的想提前知道,那就提前测试。

这几乎是一样的。对base.ctor的调用将由JITter内联,并且只执行一次分配。它只需要花费几个字节作为开销。

如果你不确定,试试一个小的基准。

我使用探查器对代码进行微优化的经验是,方法调用开销可以忽略不计。我在性能改进方面的主要优势几乎一直是:缓存频繁使用的计算,优化深层内部循环(通常通过使用直接数组索引而不是枚举(,以及避免不必要的装箱。当然,通过改进算法以减少迭代次数,所有这些都相形见绌(通常是通过引入启发式方法来尽早排除分支,或者通过将问题转换为单独的"聚合"answers"细节"阶段。(

首先,正如我在评论中所说,调用基本构造函数(和虚拟方法(对性能的影响不足以证明失去它赋予程序的可维护性和表达性是合理的。如果在这种情况下性能真的是个问题,那么结构化语言就不存在了。

现在,从设计的角度来看,问题归结为继承在您的情况下是否真的有利可图。这引发了一个问题:为什么ShapeWithOffset不能从Shape派生?如果可能的话,我可能会去掉复杂性,做一些类似的事情:

public class ShapeWithOffset : Shape
{
    public ShapeWithOffset(double xOffset)
    : this(xOffset, 0.0) {}
    public ShapeWithOffset(double xOffset, double yOffset)
    {
        // TODO - Check if arguments are correct/throw ArgumentException if not.
        XOffset = xOffset;
        YOffset = yOffset;
    }
}

在C#4中,你甚至可以写:

public ShapeWithOffset(double xOffset, double yOffset = 0.0)
{
    // TODO - Check if arguments are correct/throw ArgumentException if not.
    XOffset = xOffset;
    YOffset = yOffset;
}

正如kuchana在他的书(设计模式(中所说的那样,一般地谈论继承(而不是具体的情况(,如果没有必要,尽量避免继承,因为它很复杂。我认为运行时绑定可能会导致一些小的性能问题,但继承的主要开销是它在设计中的复杂性,这比微小的性能问题重要得多。

编辑

我现在意识到这个问题是关于构造:D。以下段落在java中是正确的,也许在中也是正确的。Net。我认为,如果你在你的子类中显式定义构造函数,这不会有任何区别,因为编译器会首先在子类中寻找构造函数,如果没有找到,它会在继承层次结构中上升,直到他!找到合适的构造函数。