继承自另一个类的类的构造函数效率较低吗?

时间:2011-04-25 14:09:58

标签: c# .net performance inheritance constructor

问题

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

我知道类创建(即构造函数调用)代价很高。我的问题是:如果我让这个小类继承自另一个类,会不会更昂贵?有些字段只会移动到超类,所以基本上我只能使用

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


问题的示例情况和演示

考虑这2个案例:

1。案例只包含一个类。这是原来的课程:

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 由2个类组成,其中second从第一个继承。第二课ShapeWithHorizontalAndVerticalOffset在1. case中提供与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);

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

5 个答案:

答案 0 :(得分:8)

这闻起来像premature optimization

你问题中的关键词是“......我想......”。如果你知道自己遇到了性能问题,那就找出瓶颈并对其进行优化。如果您预计会出现性能问题,请不要!以建议的方式使用继承会导致任何性能瓶颈的可能性极小。但是,如果你真的想提前知道,请提前测试。

答案 1 :(得分:5)

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

如果您不确定,请尝试一个小基准。

答案 2 :(得分:3)

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

答案 3 :(得分:1)

首先,正如我在评论中所说,调用基础构造函数(和虚拟方法)并不会影响性能,足以证明它失去了它为程序带来的可维护性和表现力。如果在这种情况下性能确实存在问题,那么结构化语言将不存在。

现在,从设计的角度来看,问题被简化为继承在您的情况下是否真正有利可图。这提示了一个问题:为什么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;
}

答案 4 :(得分:0)

一般性地谈论继承(特别是你的情况),因为kuchana在他的书(设计模式)中试图避免继承,如果没有必要,因为它的复杂性。 我认为运行时绑定可能会导致小的性能问题,但继承的主要开销是它的设计复杂性,这比微小的性能问题重要得多。

修改

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