Skip to content

Releases: deliciousNesquik/roman

v3.0.0

Choose a tag to compare

@deliciousNesquik deliciousNesquik released this 24 Aug 08:21

A correctness release. Five defects let the library return wrong answers silently — most
importantly, the range guard that is the entire point of the type could be bypassed by writing
roman + 1. Fixing them required breaking changes, hence the major version.

Nothing about the numeral system itself changed: the range is still 1–3999, canonical output is
identical, and every valid canonical string parses to the same value as before.

Upgrading from 2.x

2.x 3.0.0
int x = roman; int x = (int)roman; or roman.ToInt()
new Roman(3999) + 14000 throws OverflowException
roman == 42int comparison, disagreed with roman.Equals(42) Roman/int operator; the two now agree
Parse("IIX", RomanStyle.Lenient)10 8
Parse(s, (RomanStyle)7) → parsed leniently throws ArgumentOutOfRangeException
new Roman((string)null)ArgumentException ArgumentNullException

Existing catch (ArgumentException) handlers keep working — ArgumentNullException derives from it.
The compiler will point you at every site that needs the (int) cast.

Breaking changes

  • Romanint is now an explicit conversion. An implicit one made Roman's own operators
    inapplicable in any mixed expression: because intRoman is explicit, they were not
    candidates, so overload resolution fell back to the predefined int operators. `new Roman(3999)
    • 1evaluated to4000with no exception, andnew Roman(10) + 5produced theint 15rather thanXV. Use (int)romanorroman.ToInt()`.
  • Mixed Roman/int arithmetic is range-checked. + - * / now validate the result against
    1–3999 and throw OverflowException, exactly as the all-Roman operators always did. Operands
    widen to long first, so a large int operand cannot overflow the intermediate value.
  • Lenient parsing of multi-symbol subtractive runs is corrected. A symbol is subtractive when
    it is smaller than the largest symbol anywhere to its right, not merely smaller than its
    immediate neighbour. "IIX" was 10 and is now 8; "XIIX" was 20, now 18; "IIC" was
    100, now 98. Strict parsing is unaffected — it rejected these forms before and still does.
  • An undefined RomanStyle is rejected. Any value outside the declared members — from a cast
    or an uninitialized field — silently selected lenient parsing, skipping the canonical check
    entirely. It now throws ArgumentOutOfRangeException. TryParse throws as well rather than
    returning false, matching int.TryParse with an invalid NumberStyles. default(RomanStyle)
    is Strict and still parses strictly.
  • A null string throws ArgumentNullException. string.IsNullOrWhiteSpace collapsed null and
    empty into one branch, so a missing argument was reported as ArgumentException: Roman numeral cannot be empty. Empty and whitespace-only strings still throw ArgumentException.
  • AssemblyVersion now tracks the package version. Every release up to and including 2.0.1
    shipped an assembly stamped 1.0.0.0, because only PackageVersion was set and that feeds the
    nuspec alone. typeof(Roman).Assembly.GetName().Version now returns 3.0.0.
  • ArgumentException for an invalid character now names its parameter. ParamName was null;
    it is now "roman", and the message gains the usual (Parameter 'roman') suffix.

Added

  • Operators + - * /, < > <= >= and == != for (Roman, int) and (int, Roman), in both
    operand orders.

  • Equals(int) and CompareTo(int), plus IEquatable<int> and IComparable<int>, so
    roman.Equals(42) agrees with roman == 42.

  • Comparison against an int never constructs a Roman, so an unrepresentable bound is a fair
    question: new Roman(3999) < 5000 is true.

  • roman / 0 reaches DivideByZeroException, which was unreachable while both operands were
    Roman.

    operand orders.

  • Equals(int) and CompareTo(int), plus IEquatable<int> and IComparable<int>, so
    roman.Equals(42) agrees with roman == 42.

  • Comparison against an int never constructs a Roman, so an unrepresentable bound is a fair
    question: new Roman(3999) < 5000 is true.

  • roman / 0 reaches DivideByZeroException, which was unreachable while both operands were
    Roman.

Fixed

  • The leading-minus check used a culture-sensitive StartsWith(string). Under ICU, characters such
    as U+200B and U+00AD are collation-ignorable, so "\u200B-X" "started with" - and was reported
    as a sign problem rather than an invalid character — and the answer changed with the consuming
    application's globalization mode. Now ordinal (CA1310), and 11× cheaper on a check that runs once
    per parse.
  • Dead links and a mismatched table-of-contents anchor in both READMEs. README.md ships inside
    the package, so these were visible on the nuget.org page.

Compatibility

.NET 9, no dependencies. 220 unit tests.

v2.0.1

Choose a tag to compare

@deliciousNesquik deliciousNesquik released this 17 Aug 06:05

Update and rewrite all docs for private and public method. Standarting, translate and formating docs
Simplify code any methods for developer roman library

v2.0.0

Choose a tag to compare

@deliciousNesquik deliciousNesquik released this 07 Jul 07:42

Roman 2.0.0

Мажорный релиз с изменениями, ломающими обратную совместимость.

⚠️ Breaking changes

  • Разбор строк теперь строгий по умолчанию. Конструктор Roman(string), Parse(string) и
    TryParse(string, out) используют RomanStyle.Strict и отвергают неканонические формы
    (например, "IIII") с FormatException. Раньше поведение по умолчанию было лояльным.
    RomanStyle.Strict стал значением по умолчанию перечисления (0).
  • Арифметика бросает OverflowException вместо ArgumentOutOfRangeException. При выходе
    результата +, -, *, / за диапазон 1–3999 операнды сами по себе валидны — из диапазона
    выходит результат, поэтому семантически корректен OverflowException (без надуманного
    paramName). Проверки null по-прежнему бросают ArgumentNullException.

Migration

  • Нужен прежний лояльный разбор — используйте перегрузки с RomanStyle.Lenient:
    Roman.Parse("IIII", RomanStyle.Lenient) / Roman.TryParse("IIII", RomanStyle.Lenient, out _).
  • Ловите OverflowException (вместо ArgumentOutOfRangeException) на переполнении арифметики.

Прочее

  • Внутренний рефакторинг: единый метод нормализации строки перед разбором.
  • Обновлены README (EN/RU) и тесты; чистка форматирования.

v1.1.1

Choose a tag to compare

@deliciousNesquik deliciousNesquik released this 17 Jun 07:12

Roman v1.1.1

Релиз добавляет строгий режим парсинга, исправляет два бага и существенно обновляет документацию. Под капотом — переезд на namespace RomanNumerals и приведённый в порядок CI.

NuGet

  • Пакет: Roman
  • Страница на NuGet: Roman
  • Описание пакета теперь рендерится прямо на NuGet (встроенный README)

Совместимость

  • Target Framework: net9.0
  • Язык: C# 13

Новое

  • Строгий режим парсинга через перечисление RomanStyle (Lenient / Strict) — по аналогии с int.Parse(string, NumberStyles):
Roman.Parse("IV", RomanStyle.Strict);    // OK → 4
Roman.Parse("IIII", RomanStyle.Strict);  // FormatException: не каноническая запись
Roman.TryParse("IIII", RomanStyle.Strict, out var r); // false
  • Новые перегрузки Parse(string, RomanStyle) и TryParse(string, RomanStyle, out Roman?). Поведение по умолчанию (лояльный разбор) не изменилось — обратная совместимость API сохранена.

Исправления

  • implicit operator int(Roman) бросал NullReferenceException на null — теперь кидает понятный ArgumentNullException.
  • ToInt(string) переполнял int-аккумулятор на сверхдлинных строках и мог молча вернуть неверное значение в диапазоне 1–3999 вместо исключения — аккумулятор переведён на long.

Улучшения

  • Устранено дублирование таблицы «символ → значение»: Map стал единственным источником истины, парсер выводит данные из него.
  • Упрощена обработка исключений в TryParse(string) (один catch вместо избыточных двух).
  • Тестовый набор расширен до 153 тестов (было 138), включая строгий режим и регрессию на переполнение.

Документация

  • README полностью переписан в open-source стиле.
  • Добавлены две языковые версии: English и Русский с переключателем языка.
  • Бейджи приведены в соответствие с проектом (.NET 9 / C# 13).

Важно при обновлении

  • Изменён namespace: RomanRomanNumerals. Имя типа осталось Roman. Обновите using:
using RomanNumerals;
var roman = new Roman("X");

Что внутри

  • Библиотека RomanNumerals (PackageId остался Roman)
  • Набор тестов RomanNumerals.Tests (MSTest)

Установка

dotnet add package Roman --version 1.1.1

Полный список изменений: v1.0.0...v1.1.1

v1.0.0

Choose a tag to compare

@deliciousNesquik deliciousNesquik released this 08 Apr 11:41
f4496fe

Roman v1.0.0

Первый релиз библиотеки Roman для работы с римскими числами.

NuGet

Совместимость

  • Target Framework: net9.0

Что внутри

  • Библиотека Roman
  • Набор тестов Roman.Tests (MSTest)

Установка

dotnet add package Roman --version 1.0.0