Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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?

like image 454
Derek Tomes Avatar asked Mar 20 '26 02:03

Derek Tomes


2 Answers

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.

like image 198
Jon Skeet Avatar answered Mar 21 '26 14:03

Jon Skeet


String does not implement IFormattable, but your code does not use it either. You can create a wrapper class for a string to be used in scenarios where IFormattable is needed, like this:

public class FormattableString : IFormattable {
    private readonly string str;
    public FormattableString(string str) {
        this.str = str;
    }
    public string ToString() {
        return str;
    }
    public string ToString(string format, IFormatProvider formatProvider) {
        // You can add special code here to format the value of your string
        // as directed by the format passed into the method.
        return str;
    }
}

Now you can use this class as follows:

string returnValue = Foo(new FormattableString(bar));
like image 36
Sergey Kalinichenko Avatar answered Mar 21 '26 16:03

Sergey Kalinichenko



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!