Объявление / передача структур против объявления / передачи отдельных значений - PullRequest
0 голосов
/ 19 февраля 2010

У меня есть два вопроса, на самом деле.Но они очень тесно связаны.

Предположим, у меня есть простой 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, и поэтому, несмотря на то, что одинаковый объем данных передается / устанавливается в описанных выше методах, первый и последний из них могут быть немного более эффективными.Это правда?И отличаются ли первый и последний методы от других?

Для записи: Я не спрашиваю об этом, потому что ошибочно полагаю, что это способствует узкому месту в производительности или что это особенно важно с точки зрения дизайна (хотя, возможно, кто-то удивит меня, заявив, что делает ).Я спрашиваю, потому что мне просто любопытно.

Ответы [ 3 ]

5 голосов
/ 19 февраля 2010

У вас есть большие проблемы, чтобы разобраться в первую очередь. Этот код плохо пахнет.

Проблема № 1: вы используете двоичное число с плавающей запятой для представления финансового количества. Двоичные числа с плавающей запятой предназначены для представления научных величин, в которых крошечные ошибки в последних нескольких битах точности не важны. Они крайне непригодны для представления точных финансовых показателей. Если вы представляете финансовые суммы, всегда используйте десятичную, никогда не используйте float.

Проблема № 2: Предположим, что у вас была веская причина использовать двоичную с плавающей точкой, не используйте float. Используйте двойной. Современное оборудование оптимизировано для выполнения арифметики двойной точности, а не одинарной точности; Есть ситуации, в которых единичная точность на самом деле медленнее. Конечно, double занимает вдвое больше памяти, чем float, но если у вас в памяти нет нескольких миллионов одновременно, это действительно не имеет значения. Кроме того, вы все равно должны использовать десятичную дробь, которая в четыре раза больше, чем float.

Проблема № 3: у вас есть изменяемый тип значения. Изменчивые типы значений являются чистым злом. Это так легко случайно вызвать ошибки с изменяемыми типами значений. Избегайте избегайте избегайте.

Проблема № 4: Это действительно правильное имя для структуры? Я думаю, что «торговая цена» будет представлена ​​свойством Price. Есть ли лучшее название для этой вещи, которая более четко описывает то, что она представляет? Представляет ли это какую-то четкую концепцию в вашей сфере деятельности?

Проблема № 5: Вы не проверяете аргументы, передаваемые общедоступному конструктору публичной структуры. Это кажется опасным. Что если кто-то попытается обменять -100 акций по цене -100000.00 за акцию. Что просходит? Ничего хорошего, держу пари.

Проблема № 6: Значением по умолчанию для структуры всегда должен быть допустимый экземпляр структуры. Это? Экземпляр этой структуры по умолчанию: Price = 0, Quantity = 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; 
    } 
} 

Что касается ваших актуальных вопросов: нет логической разницы. может иметь разницу в производительности. У меня нет ни малейшего представления о том, есть ли здесь ощутимая разница в производительности или нет. Вы уже написали код в обоих направлениях. Возьми секундомер, запусти его миллиард раз в обе стороны, и тогда ты узнаешь ответ на свой вопрос.

4 голосов
/ 19 февраля 2010

Передача структур вместо отдельных значений может привести к лучшему удобству сопровождения, потому что если вам когда-либо понадобится изменить определение структуры, влияние изменения кода будет ниже.

0 голосов
/ 27 ноября 2012

Структура, например, с тремя полями, очень похожа на группу из трех переменных, склеенных клейкой лентой.При выделении поля или переменной типа структуры выделяется пространство для этих трех отдельных полей, а передача значения типа структуры по значению имеет по существу те же затраты времени выполнения, что и передача этих трех полей отдельно.

Основные различия между структурой и группой отдельных переменных: (1) один массив типа структуры содержит все поля структуры в каждом элементе.Таким образом, если MyPoint3d является структурой, один массив из 50 элементов будет содержать все 50 значений x, y и z.Если бы вы использовали отдельные поля для разных координат, нужно было бы создать три разных массива;(2) передача структуры любого размера в качестве параметра ref требует передачи только одной ссылки.Код, который принимает параметр ref типа структуры (например, MyPoint3d), будет знать, что члены x, y и z, к которым осуществляется доступ по этой ссылке, принадлежат одному и тому же экземпляру структуры.Напротив, если бы код принимал параметр ref для координаты x, другой для y и другой для z, он не мог бы знать, действительно ли они были x, yz координаты одной точки.

Кстати, для структур хорошо иметь открытые открытые поля (если структура должна представлять набор переменных, лучшего способа показать это не существует), но этоплохо для структурных методов для модификации this.Лучше использовать статический метод, который принимает параметр ref типа структуры.Компиляторы будут кричать, если будет предпринята попытка передать структуру только для чтения в качестве объявленного параметра ref;напротив, они не будут кричать, если будет предпринята попытка передать структуру, доступную только для чтения, методу, который модифицирует this.Сгенерированный код не будет работать , но он не будет генерировать никакой диагностики компилятора.Использование явного параметра ref гарантирует, что код, который не будет работать, не будет компилироваться.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...