The answer posted by the question asker is generally considered to be the correct approach. When you have a generic method that has to do something special for one particular type, it is no longer generic.
That said, first, the actual question never got answered, and second, there are some caveats about this approach to consider.
This is not working because it says "cannot convert T to double". Is there a way to fix this?
Yes, there are a couple of ways to do it, and some of them are better than others.
First off, this is in general a bad way to type test.
typeof(T) == typeof(double)
You have two Ts in hand, so instead you would do this:
protected void Set<T>(ref T storage, T value, blah blah blah)
{
if (Equals(storage, value))
return;
double? oldValue = storage as double?;
double? newValue = value as double?;
if (oldValue != null && newValue != null && Negligible(oldValue.Value, newValue.Value))
return;
...
Note that a bad way to do it is:
protected void Set<T>(ref T storage, T value, blah blah blah)
{
if (Equals(storage, value))
return;
if (storage is double && value is double)
{
double oldValue = (double)(object)storage;
double newValue = (double)(object)value;
if (Negligible(...
Because this takes on a boxing penalty; the jitter is not necessarily smart enough to optimize away the double -> object -> double step, which is expensive.
Though as I said, in general its a good idea to specialize if possible, consider the following situation. If you specialize and make one version that does doubles and one that does everything else, then:
Set(ref someDouble, 1.23)
will call the double version, but
Set<double>(ref someDouble, 1.23)
will still call the generic version. C# prefers the non-generic version to the generic version, but if you explicitly ask for the generic version, you'll get it.
Similarly, if you are called from a generic context:
class C<T>
{
T storage;
void Frob(Blah blah, T value) {
blah.Set<T>(ref storage, value);
}
Then C<double>
does not call your special version; again, this calls Set<double>
as requested.
So be cautious.