Q:

GENERIC C# way to round a number to a nearest multiple? (Not a duplicate, has a specific angle & proposed answer)

I have a C# extension method as follows:
public static double RoundOff(this double rawNumber, double roundToNearest)
{
    double rawMultiples     = rawNumber / roundToNearest;
    double roundedMultiples = Math.Round(rawMultiples);
    double roundedNumber    = roundedMultiples * roundToNearest;
    return roundedNumber;
}

I don't want to write it multiple times for all the different numeric types (int, decimal, etc.)
Is there a way to do it generically, like this?
public static double RoundOff<T>(this T rawNumber, T roundToNearest)
    where T : [SOME CONSTRAINT]
{
    T rawMultiples     = rawNumber / roundToNearest;
    T roundedMultiples = Math.Round(rawMultiples);
    T roundedNumber    = roundedMultiples * roundToNearest;
    return roundedNumber;
}

It would be so so useful to be able to do this more generally.  Less code to maintain - and more power from just one extension method!
If it can't be done, is it because C# can't be extended to work in this way?  Or might it one day be extended to allow an "all numeric types" generic constraint?
Any ideas welcomed.
UPDATE
In response to a challenge about similarity to another question.  Yes, it is similar in terms of the subject matter but is different because I am after a specific solution to a specific problem.  I have added my own attempted answer below to clarify.  Challenges welcome if anyone still thinks I have missed the point.

A:

I accept that this question bears some similarity to others - but my query is a very specific one about solving a very specific problem.
I want to share my own workaround solution here.  On the plus side, it's fully generic.  On the minus side, it is slow as it uses Decimals but this can be adjusted to faster doubles if required.
    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");
        }
    }

And this extension method with logic borrowed from the cited answer
    public static bool IsNumericType(this object o)
    {
        // https://stackoverflow.com/questions/1749966/c-sharp-how-to-determine-whether-a-type-is-a-number
        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;
        }
    }

It's not without its weaknesses, but it does do what I'm after.
One self-criticism: because we're rounding-off, the extra precision of decimals could be unnecessary - but intuitively it seems better to use a high-precision type.  I could be wrong in this and maybe someone more knowledgeable can shed some insight.
So I hope this either helps someone or provokes an avalanche of angry responses as to how it can be done better!!

