声明/传递结构与声明/传递单个值(Declaring/passing structs vs. dec

2019-10-19 20:02发布

我有两个问题,其实。 但是,他们的关系非常密切。

假设我有一个简单的struct是这样的:

public struct TradePrice {
    public float Price;
    public int Quantity;

    public TradePrice(float price, int quantity) {
        Price = price;
        Quantity = quantity;
    }
}

问题1

现在,如果我有代码的地方,需要访问这些值,有没有这样做有什么区别:

TradePrice tp = new TradePrice(50.0f, 100);

和这个:

float p = 50.0f;
int q = 100;

我觉得第一个,因为它是调用构造函数,应该是这样一个方法调用的开销。 但是,这只是一个猜测。

问题2

回答上述问题实际上很可能回答这个问题为好,但也许有一些细微之处,使这些情景不同; 所以我会问反正。 假设我有一个struct ,其本身所具有的成员是struct类型。 像这样:

public struct BidAsk {
    public TradePrice Bid;
    public TradePrice Ask;
}

然后会有这三种方法之间有什么区别?

Reset(TradePrice bid, TradePrice ask) {
    Bid = bid;
    Ask = ask;
}

Reset(float bidPrice, int bidQuantity, float askPrice, int askQuantity) {
    Bid = new TradePrice(bidPrice, bidQuantity);
    Ask = new TradePrice(askPrice, askQuantity);
}

Reset(float bidPrice, int bidQuantity, float askPrice, int askQuantity) {
    Bid.Price = bidPrice;
    Bid.Quantity = bidQuantity;
    Ask.Price = askPrice;
    Ask.Quantity = askQuantity;
}

倾向于认为有一些开销到构造的struct ,所以即使相同的数据量被传递/在上述方法中,第一个和最后的可能会稍微更有效。 这是真的? 并且是第一个和最后一个方法,甚至是不同的?

为了记录在案, 我不是问这个,因为我错误地认为这是从设计的角度来看有助于性能瓶颈或者说,它特别的问题 (尽管也许有人会辩称它确实让我感到吃惊)。 我问,因为我只是好奇。

Answer 1:

你有更大的问题先解决。 此代码味道不好。

问题1:您使用的是二进制浮点数字来表示金融数量。 二进制浮点数字设计代表科学的数量在哪里精度的最后几位微小的错误是不重要的。 他们是非常不适合代表正确的财务数量。 如果您是代表经常使用十进制金融数量,从来不使用浮动。

问题2:假设你有一个很好的理由使用二进制浮点,不使用浮动。 双用。 现代硬件被优化,以做的双精度运算,而不是单精度; 存在其中单精度实际上是比较慢的情况。 当然,双占用两倍的内存浮动,但除非你已经在内存中得到了这些几万元一次,它其实并不重要。 除此之外,你应该使用十进制无论如何,这比浮动的四倍。

问题3:你有一个可变的值类型。 可变的值类型是纯粹的邪恶。 这是很容易不小心引起​​可变的值类型的错误。 避免避免避免。

问题4:那是真正为结构正确的名称? 我会认为,“交易价格”将由价格属性来表示。 是否有这个东西更清楚地说明它代表什么更好的名字? 这是否代表了你的业务领域一些清晰的概念?

问题5:你做传递到一个公共结构的公共构造函数的参数没有验证。 这似乎是危险的。 如果有人试图在-100000.00每股价格交易-100万股。 怎么了? 没事找事,我打赌。

问题6:struct的默认值应该总是结构的有效实例。 是吗? 这个结构的默认实例是价格= 0,数量= 0。确实,实际上有意义吗? 如果没有,那就不要使这个结构。 使它成为一个类。

问题#7:这是逻辑上的首位值类型? 为什么是一个结构? 这是东西,你觉得应该在逻辑上被视为一个值,如12号,或逻辑上的东西,你可以参考“同样的事情,”在多个位置,就像一个客户? 如果不是逻辑值,不使用值类型。

假设名称是正确的,这在逻辑上是值类型,你的代码应该是这样的:

public struct TradePrice 
{ 
    public decimal Price {get; private set;}
    public int Quantity {get; private set; }
    public TradePrice(decimal price, int quantity) : this()
    { 
        if (price < 0m) throw new ...
        if (quantity < 0) throw new ...
        this.Price = price; 
        this.Quantity = quantity; 
    } 
} 

至于你的实际问题:没有逻辑上的区别。 可能有性能差异。 我还没有得到是否有在不在一个可衡量的业绩差异最微弱的想法。 你已经writen代码两种方式。 获取秒表,运行十亿次左右逢源,然后你就会知道回答你的问题。



Answer 2:

传递结构,而不是单独的值可能会导致更好的可维护性,因为如果你需要更改结构定义的代码变化的影响会更低。



Answer 3:

与例如三个字段的结构的行为很像一组用胶带粘在一起三个变量。 分配结构类型的字段或变量用于这三个单独的字段分配空间,并且由值传递的结构类型的值具有基本上相同的运行时间成本会分别使三个字段。

相对于一组单独的变量的结构之间的主要差别是:(1)结构类型的一个单个阵列保存所有在各元件结构体的领域。 因此,如果MyPoint3d是一个结构,50种元素的一个阵列将持有的所有50个值xy ,和z 。 如果一个分别使用字段为不同的坐标,一个人必须要创建三个不同的阵列; (2)通过一个任意大小的结构作为一个ref参数只需要通过一个单一的参考。 它接受一个代码ref的结构类型(例如,参数MyPoint3d )将知道xyz经由参考访问成员的所有属于同一个结构实例。 相反,如果代码接受一个ref参数x坐标,另一个用于y ,另一个用于z ,就无法知道它们实际上的方式xy ,和z单点的坐标。

顺便说一句,这是罚款结构已经公开的公共领域(如一个结构应该代表的变量的集合,有没有更好的方式来表明),但它的坏的结构方法来修改this 。 这是更好地利用它接受一个静态方法ref的结构类型的参数。 编译器将鸣叫如果试图通过只读结构作为声明ref参数; 相反,如果试图以一个只读结构传递给它修改的方法,他们不会鸣叫this 。 生成的代码将无法正常工作 ,但不会产生任何编译器诊断。 使用一个明确的ref参数将确保代码将无法正常工作,将无法编译。



文章来源: Declaring/passing structs vs. declaring/passing individual values