C# 从另一个类继承的类的构造函数是否效率较低? 问题:

C# 从另一个类继承的类的构造函数是否效率较低? 问题:,c#,.net,performance,inheritance,constructor,C#,.net,Performance,Inheritance,Constructor,在我的应用程序中,我创建了大量只保存一些数据的“小”类实例 我知道类创建(即构造函数调用)代价高昂。我的问题是:如果我让这个小类从另一个类继承,成本会更高吗?一些字段将移动到超类,所以基本上我可以使用 注意:此问题专门针对.NET中的性能 示例情况和问题的演示 考虑这两种情况: 1。案例只包含一个类别。它是原始类: public class ShapeWithOffset{ public double XOffset { get; private set; } public d

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

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

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


示例情况和问题的演示 考虑这两种情况:

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由两个类组成,其中第二个类继承第一个类。第二类
shapeWithHorizontal and VerticalOffset
提供了与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
}
我的问题是:iscommand
varfoo=newshapewhotoffset(20,10,shape)快于
var boo=带有水平和垂直偏移的新形状(20,10,shape)

如果我使用合成而不是继承,它将是。。。但是继承呢?

这闻起来像


你问题中的关键词是“……我想……”。如果你知道你有一个性能问题,那么找出瓶颈并优化它。如果您预期会出现性能问题,请不要!以您建议的方式使用继承不太可能导致任何性能瓶颈。但是,如果你真的想提前知道,那就提前测试。

这几乎是一样的。 对base.ctor的调用将通过抖动内联,分配只执行一次。作为开销,您只需花费几个字节


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

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

现在,从设计的角度来看,问题是继承在您的案例中是否真的有利可图。这提示了一个问题:
shapewhoffset
为什么不能从
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中也是正确的。
我认为,如果在子类中显式定义构造函数,这不会有任何区别,因为编译器将首先在子类中查找构造函数,如果没有找到,它将在继承层次结构中上升,直到他!找到合适的构造函数。

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

每个对象实例最多可以保存一个函数调用,即,如果您能原谅我的话,与您从继承中获得的可维护性和表达能力相比,在性能方面是微不足道的。然而,您是否应该在您的特定案例中实际使用继承,这是一个非常主观的问题,值得商榷(这就是为什么这是一个评论,而不是一个答案)。也就是说,问题“这里有两种编写代码的方法;哪种更快?”您已经用两种方法编写了代码;两种方法都试一下,看看哪个更快。人们似乎认为社区有一种神奇的方式,不用尝试就能知道哪两件事更快。没有这样神奇的方法。试一试,测量结果,然后你就会知道。@drasto:让我这样说:我也没有你想要的知识,我向你保证,我对编译器的了解比绝大多数人都多。当我需要一个性能问题的答案时,我会双向编写代码并进行尝试。多年的经验告诉我,我对性能差异的真正原因的猜测常常是完全错误的。DeStSo:“我们没有人拥有你所知道的知识,也就是说你认为是一个重要的性能差异。”有些人认为几纳秒的差异是非常重要的;有些人认为十分钟的差异是无关紧要的。我们中没有人能告诉你什么样的绩效指标对你和你的客户来说是重要的。@drasto:我认为没有那么清楚。例如,考虑基础呼叫是否被内联的问题。可能是,可能不是,不试一下我不知道。现在考虑内联的性能成本;它删除了一级间接寻址,即两条指令,这需要更多的时间。它增加了调用站点的代码大小,这可能会更改内存中代码的布局,从而可能导致额外的缓存丢失。现在你已经用一纳秒换了一秒