Я согласен, что этот вопрос имеет некоторое сходство с другими, но мой запрос очень специфичен в отношении решения очень специфической проблемы.
Я хочу поделиться своим собственным решением для обхода проблемы здесь.С другой стороны, он полностью универсален.С другой стороны, он медленный, так как использует десятичные дроби, но при необходимости его можно настроить на более быстрое удвоение.
public static T RoundOff<T>(this T rawNumber, T roundToNearest)
where T : IComparable<T>
{
if (typeof(T).IsNumericType())
{
decimal decimalRoundToNearest = Convert.ToDecimal(roundToNearest);
decimal rawMultiples = Convert.ToDecimal(rawNumber) / Convert.ToDecimal(roundToNearest);
decimal decimalRoundedMultiples = Math.Round(rawMultiples);
decimal decimalRoundedNumber = decimalRoundedMultiples * decimalRoundToNearest;
return (T)Convert.ChangeType(decimalRoundedNumber, typeof(T));
// alternative
// TypeConverter converter = TypeDescriptor.GetConverter(typeof(T));
// return (T)converter.ConvertFrom(decimalRoundedNumber);
}
else
{
throw new Exception("Type " + typeof(T) + " is not numeric");
}
}
И этот метод расширения с логикой заимствован из цитируемого ответа
public static bool IsNumericType(this object o)
{
// /1281215/c-kak-opredelit-yavlyaetsya-li-tip-chislom
switch (Type.GetTypeCode(o.GetType()))
{
case TypeCode.Byte:
case TypeCode.SByte:
case TypeCode.UInt16:
case TypeCode.UInt32:
case TypeCode.UInt64:
case TypeCode.Int16:
case TypeCode.Int32:
case TypeCode.Int64:
case TypeCode.Decimal:
case TypeCode.Double:
case TypeCode.Single:
return true;
default:
return false;
}
}
Не без его слабостей, но он делает то, что мне нужно.
Одна самокритика: поскольку мы округляем, дополнительная точность десятичных дробей может быть ненужной - но интуитивно это кажетсялучше использовать высокоточный тип.Я могу ошибаться в этом, и, возможно, кто-то более знающий может пролить некоторую проницательность.
Так что я надеюсь, что это или кому-то поможет, или спровоцирует лавину гневных ответов о том, как это можно сделать лучше !!