Создание структуры, которая инициализирует новый экземпляр типа данных, данный [duplicate]

Также:

observeEvent(c( 
  input$spec_button,
  mainplot.click$click
), { ... } )
23
задан ErnieL 7 November 2011 в 20:41
поделиться

4 ответа

Есть ли способ сделать MinValue / MaxValue const вместо readonly?

No. Однако BCL тоже этого не делает. Например, DateTime.MinValue - static readonly. Ваш текущий подход для MinValue и MaxValue подходит.

Что касается ваших двух других вопросов - удобство использования и самого шаблона.

Лично я бы избегал автоматических преобразований (неявные операторы преобразования) для типа «температуры», подобного этому. Температура не является целочисленным значением (на самом деле, если вы были , чтобы сделать это, я бы сказал, что она должна быть плавающей точкой - 93,2 градуса C. Совершенно верно.) Обработка температуры как целого , и особенно нецелесообразно рассматривать любое целочисленное значение, поскольку температура кажется неуместной и потенциальной причиной ошибок.

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

 Celsius c = new Celcius(41);

Не намного сложнее, чем неявное преобразование из целого числа. Однако это намного яснее.

20
ответ дан Reed Copsey 18 August 2018 в 01:52
поделиться
  • 1
    +1 для написания хорошей записи и предупреждения об использовании int в этом случае. – JonH 7 November 2011 в 20:57
  • 2
    Благодарю. Я вижу вашу точку зрения на неявный оператор для построения. Вы находите как можно больше проблем с оператором-невязким оператором int (Celsius c)? С ясности точки зрения это похоже на kill: int i = (int) c; – ErnieL 8 November 2011 в 01:09
  • 3
    @ErnieL Мне на самом деле это не нравится - температура не является произвольным числом - я не вижу смысла в разрешении неявного преобразования, поскольку он имеет тенденцию вызывать другие проблемы. Я считаю, что принудительное явное преобразование, как правило, более безопасно в долгосрочной перспективе ... – Reed Copsey 8 November 2011 в 01:28

DebuggerDisplay полезен. Я бы добавил единицы измерений «{m_value} C», чтобы вы могли сразу увидеть тип.

В зависимости от использования цели вы также можете иметь общую структуру преобразования в / из базовых блоков в дополнение к конкретному классы. То есть хранить значения в единицах СИ, но иметь возможность отображать / редактировать на основе культуры (градусы C, км, кг) против (градусов F, mi, lb).

Вы также можете проверить измерение F # единицы для additioanl идей ( http://msdn.microsoft.com/en-us/library/dd233243.aspx ) - обратите внимание, что это компиляция времени.

2
ответ дан Alexei Levenkov 18 August 2018 в 01:52
поделиться

Я думаю, что с точки зрения удобства использования я бы выбрал тип Temperature, а не Celsius. Celsius - это всего лишь единица измерения, а Temperature будет представлять собой фактическое измерение. Тогда ваш тип может поддерживать несколько единиц, таких как Цельсия, Фаренгейта и Кельвина. Я бы также выбрал десятичное значение в качестве резервного хранилища.

Что-то в этих строках:

public struct Temperature
{
    private decimal m_value;

    private const decimal CelsiusToKelvinOffset = 273.15m;

    public static readonly Temperature MinValue = Temperature.FromKelvin(0);
    public static readonly Temperature MaxValue = Temperature.FromKelvin(Decimal.MaxValue);

    public decimal Celsius
    {
        get { return m_value - CelsiusToKelvinOffset; }
    }

    public decimal Kelvin 
    {
        get { return m_value; }
    }

    private Temperature(decimal temp)
    {
        if (temp < Temperature.MinValue.Kelvin)
               throw new ArgumentOutOfRangeException("temp", "Value {0} is less than Temperature.MinValue ({1})", temp, Temperature.MinValue);
        if (temp > Temperature.MaxValue.Kelvin)
               throw new ArgumentOutOfRangeException("temp", "Value {0} is greater than Temperature.MaxValue ({1})", temp, Temperature.MaxValue);
         m_value = temp;
    }

    public static Temperature FromKelvin(decimal temp)
    {     
           return new Temperature(temp);
    }

    public static Temperature FromCelsius(decimal temp)
    {
        return new Temperature(temp + CelsiusToKelvinOffset);
    }

    ....
}

Я бы избегал неявного преобразования, поскольку Рид утверждает, что он делает вещи менее очевидными. Однако я бы перегрузил операторы (& lt ;,>, ==, +, -, *, /), поскольку в этом случае было бы целесообразно выполнять такие операции. И кто знает, в какой-то будущей версии .net мы могли бы даже указывать ограничения оператора и, наконец, могли бы писать более многократно используемые структуры данных (представьте себе класс статистики, который может вычислять статистику для любого типа, который поддерживает +, -, *, /).

9
ответ дан ChrisWue 18 August 2018 в 01:52
поделиться
  • 1
    +1 для операторов сравнения и базового температурного класса ... Не так уверен в свойствах преобразования - возможно, это сработает в некоторых случаях. Я бы рассмотрел шаблон ToString / Parse с прохождением пользовательской "единицы измерения" string вместо Temperature.ToString("C")). – Alexei Levenkov 8 November 2011 в 05:04
  • 2
    @Alexei: Да, пользовательский синтаксический анализ на основе единиц работает хорошо, btdt. – ChrisWue 8 November 2011 в 08:35
  • 3
    Мне нравятся FromKelvin () и FromCelsius (). Я думаю, что вы и @Reed Cospsey правильно указали, что DateTime - лучшая модель BCL для имитации, чем int для того, что хранится. – ErnieL 8 November 2011 в 08:36
  • 4
    +1: Это действительно очень, очень похоже на некоторые из моих текущих типов (включая тип температуры). Я не всегда согласен с выбором десятичного числа здесь, хотя - двойное, скорее всего, имеет большой диапазон и точность для большинства применений температуры, поэтому я использовал его. Также - на стороне примечание, конструктор, как написано, не будет компилироваться - он пытается сравнить десятичную с температурой, что потребует неявных преобразований. Я работаю над этим в шахте, используя private const double для значений Min / Max и использую это для сравнений и для сборки readonly-структур. – Reed Copsey 8 November 2011 в 20:35
  • 5
    @Reed: вы можете перегрузить & lt; и & gt; вместо. Однако я исправил его в коде. – ChrisWue 8 November 2011 в 20:48

Я думаю, что это идеальный шаблон реализации для типов значений.

. В любом случае, поскольку Celsius неявно конвертируется в / из int, вы можете определить такие границы:

public const int MinValue = -273;
public const int MaxValue = int.MaxValue;

Однако в действительности нет никакой практической разницы между static readonly и const.

0
ответ дан kprobst 18 August 2018 в 01:52
поделиться
  • 1
    Я бы не указал Min / MaxValue как ints. Они должны быть того же типа, в которых они содержались. Imagine DateTime.Min / MaxValue будет иметь тип int - это будет казаться довольно странным. Также это своего рода утечки внутренних элементов (тип поля поддержки), что не очень хорошо, если вы хотите / должны изменить вашу реализацию. – ChrisWue 8 November 2011 в 08:39
  • 2
    Const - время компиляции. Readonly - это время выполнения. В этом случае разница велика, потому что для создания readonly MaxValue требуется вызов конструктора, а конструктор зависит от уже определенного MaxValue. Одна из причин, по которой я опубликовал этот вопрос, нашел хороший выход из этого круга. – ErnieL 8 November 2011 в 17:20