Единицы измерения в C# - почти

57
задан Community 23 May 2017 в 12:09
поделиться

6 ответов

Вы пропускаете размерный анализ. Например (из ответа Вы связались с), в F#, можно сделать это:

let g = 9.8<m/s^2>

и это генерирует новую единицу ускорения, полученного из метров и секунды (можно на самом деле сделать то же самое в шаблонах использования C++).

В C#, возможно сделать размерный анализ во времени выполнения, но это добавляет наверху и не приносит Вам пользу времени компиляции, проверяя. Насколько я знаю, что нет никакого способа сделать полные единицы времени компиляции в C#.

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

, Если Вы интересуетесь тем, как сделать это во времени выполнения, идея состоит в том, что каждое значение имеет скалярную величину и целые числа, представляющие питание каждой основной единицы.

class Unit
{
    double scalar;
    int kg;
    int m;
    int s;
    // ... for each basic unit

    public Unit(double scalar, int kg, int m, int s)
    {
       this.scalar = scalar;
       this.kg = kg;
       this.m = m;
       this.s = s;
       ...
    }

    // For addition/subtraction, exponents must match
    public static Unit operator +(Unit first, Unit second)
    {
        if (UnitsAreCompatible(first, second))
        {
            return new Unit(
                first.scalar + second.scalar,
                first.kg,
                first.m,
                first.s,
                ...
            );
        }
        else
        {
            throw new Exception("Units must match for addition");
        }
    }

    // For multiplication/division, add/subtract the exponents
    public static Unit operator *(Unit first, Unit second)
    {
        return new Unit(
            first.scalar * second.scalar,
            first.kg + second.kg,
            first.m + second.m,
            first.s + second.s,
            ...
        );
    }

    public static bool UnitsAreCompatible(Unit first, Unit second)
    {
        return
            first.kg == second.kg &&
            first.m == second.m &&
            first.s == second.s
            ...;
    }
}

, Если Вы не позволяете пользователю изменять значение единиц (хорошая идея так или иначе), Вы могли добавить подклассы для общих единиц:

class Speed : Unit
{
    public Speed(double x) : base(x, 0, 1, -1, ...); // m/s => m^1 * s^-1
    {
    }
}

class Acceleration : Unit
{
    public Acceleration(double x) : base(x, 0, 1, -2, ...); // m/s^2 => m^1 * s^-2
    {
    }
}

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

41
ответ дан Matthew Crumley 24 November 2019 в 19:34
поделиться

Используя отдельные классы для различных единиц той же меры (например, cm, мм и ft для Длины) кажется довольно странным. На основе Платформы.NET DateTime и классы TimeSpan, я ожидал бы что-то вроде этого:

Length  length       = Length.FromMillimeters(n1);
decimal lengthInFeet = length.Feet;
Length  length2      = length.AddFeet(n2);
Length  length3      = length + Length.FromMeters(n3);
17
ответ дан Mark Cidade 24 November 2019 в 19:34
поделиться

существует jscience: http://jscience.org/ , и вот отличный dsl для единиц: http://groovy.dzone.com/news/domain-specific-language-unit - . iirc, c# имеет закрытия, таким образом, необходимо быть в состоянии мостить что-то.

1
ответ дан Ray Tayek 24 November 2019 в 19:34
поделиться

Почему бы не использовать CodeDom для генерации всех возможных перестановок единиц автоматически? Я знаю, что это не является лучшим - но я буду определенно работать!

0
ответ дан Jonathan C Dickinson 24 November 2019 в 19:34
поделиться

Посмотрите Шиканье Ometa (который будет доступен для Шиканья 1.0): Шиканье Ometa и Расширяемый Парсинг

0
ответ дан justin.m.chase 24 November 2019 в 19:34
поделиться

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

var mass = 1.Kilogram();
var length = (1.2).Kilometres();

На самом деле это не соглашение .NET и, возможно, не самая открываемая функция, поэтому, возможно, вы бы добавили их в специальное пространство имен для людей, которым они нравятся, а также предложили бы больше традиционные методы строительства.

18
ответ дан 24 November 2019 в 19:34
поделиться
Другие вопросы по тегам:

Похожие вопросы: