Вам не хватает анализа размеров. Например (из ответа, на который вы ссылаетесь), в 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
{
}
}
Вы также можете определить более специфические операторы для производных типов, чтобы избежать проверки совместимых единиц для общих типов.