"No overload for method 'ToString' takes 1 arguments" in a C# generic method

995 Views Asked by At

I am trying to write a C# generic method that accepts nullable decimal and double values and converts them to a string representation.

I am getting the error "No overload for method 'ToString' takes 1 arguments" although I am accessing .Value of the nullable parameter.

Here is my code. What am I doing wrong?

public static string ToThousandSeparated<T>(T? value, string naString = "") where T : struct
{
    if (value.HasValue)
    {
        T val = value.Value;
        return val.ToString("N0");
    }

    return naString;
}
2

There are 2 best solutions below

3
canton7 On BEST ANSWER

object only defines the method string ToString() (with no parameters). Objects like Int32 define their own string ToString(string) method.

However, there's a useful interface called IFormattable, which provides a string ToString(string, IFormatProvider) method. So you can either constrain yourself to all T which implement IFormattable:

public static string ToThousandSeparated<T>(T? value, string naString = "")
    where T : struct, IFormattable
{
    if (value.HasValue)
    {
        T val = value.Value;
        return val.ToString("N0", null);
    }

    return naString;
}

or accept anything, but test whether it implements IFormattable at runtime:

public static string ToThousandSeparated<T>(T? value, string naString = "")
    where T : struct
{
    if (value.HasValue)
    {
        T val = value.Value;
        return val is IFormattable formattable ? formattable.ToString("N0", null) : val.ToString();
    }

    return naString;
}
0
DekuDesu On

When you use .ToString() there are two places it will look to see for overload resolution.

It will first check to see if the object you're calling has overloaded the ToString method.

If it hasn't it will by default call Object.ToString.

In your example you want to use a nullable decimal, which DOES override ToString with several versions that accept parameters.

However, since you're calling it from a generic method, the compiler has no way of knowing the object you're calling ToString() on is a decimal all it knows is that T is a struct.

Consider checking to see if the object is an IFormattable using the is operator