Я экспериментирую с новой поддержкой общей математики в .NET 7 и пытаюсь выяснить, есть ли лучший способ выразить константы, которые не равны 1 или 0. В приведенной ниже функции я могу построить 9, но до идеала явно далеко...
public static T DigitalRoot<T>(T value) where T : IBinaryInteger<T> {
var x = T.Abs(value: value);
var y = T.Min(x: x, y: T.One);
var z = (T.One + T.One + T.One + T.One + T.One + T.One + T.One + T.One + T.One);
return (y + ((x - y) % z));
}
или (T.One << 3) + T.One
Как насчет T.CreateChecked(9)? Смотрите документы.
@МВГ. Это должен быть ответ.
Сделайте свой класс универсальным (вместо метода) и объявите то, что ближе всего к константе: private static readonly T Nine = T.CreateChecked(9);
Если вы ищете константы времени компиляции, которые, возможно, стоит вызвать более явно. Для C# я не знаю, сколько из этого указано на уровне языка, т.е. есть ли что-то, что говорит компиляторам, что ваши выражения 1+1…1 должны превращаться в одну константу, или запрещает им вычислять CreateChecked во время компиляции .
@MvG Извините, я думал, что мой комментарий был удален достаточно быстро. Была ли моя вина в том, что я случайно объявил свойство вместо поля.





Объявите поле static readonly и инициализируйте его с помощью T.CreateChecked(9), как это было предложено @MvG. Это близко к константе:
internal static class BinaryIntegerConstants<T> where T : IBinaryInteger<T>
{
public static readonly T Nine = T.CreateChecked(value: 9);
}
public static class UncategorizedFunctions
{
public static T DigitalRoot<T>(this T value) where T : IBinaryInteger<T>
{
var x = T.Abs(value: value);
var y = T.Min(x: x, y: T.One);
var z = BinaryIntegerConstants<T>.Nine;
return y + ((x - y) % z);
}
}
Контрольная работа:
Console.WriteLine(15.DigitalRoot());
Примечание: идею извлечь константы в отдельный класс и превратить метод в метод расширения предложил @Kittoes0124.
(T.One + T.One + T.One) * (T.One + T.One + T.One)немного короче, но согласен, все равно не идеально.