Search code examples
c#.netiformattable

Function with IFormattable parameter won't accept a String


I have a function where I processed a string input.

    public string Foo(string text)
    {
        // do stuff with text and
        // return processed string
    }

I was calling this from a lot of places where I was converting a guid to a string like this:

string returnValue = Foo(bar.ToString());

What I actually wanted was to accept as an input any object type that could be converted to a string. So I tried modifying the function as follows:

    public string Foo(IFormattable text)
    {
        var textAsString = text.ToString();
        // do stuff with textAsString 
        // and return processed string
    }

This means all my calls are simpler:

string returnValue = Foo(bar);

It works for all object types that have a .ToString method; Except strings :)

If I try passing a string to the function I get the following compile error:

Argument type 'string' is not assignable to parameter type 'System.IFormattable'  

Which seems really odd because String HAS a ToString() method.

Why doesn't this work?


Solution

  • Simply put, System.String doesn't implement IFormattable.

    If the documentation isn't enough for you:

    object x = "a string";
    Console.WriteLine(x is IFormattable); // False
    

    Given that ToString() is declared on object, why not just have:

    public string Foo(object text)
    {
        var textAsString = text.ToString();
        // do stuff with textAsString 
        // and return processed string
    }
    

    Indeed, the ToString() method declared by IFormattable isn't the one you were trying to call anyway - you weren't passing a format string or a format provider.

    Additionally:

    Which seems really odd because String HAS a ToString() method.

    Interfaces aren't duck-typed. Just because a type has all the members required by an interface doesn't mean that it implements the interface.