Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can a method(FormattableString x) overload be called by default when the argument is an interpolated string?

Tags:

c#

I have a logging scenario where two overloads are used, for string and for FormattableString:

class Logger
{
    public static void Log(string s)
    { 
        Console.WriteLine("It's a string");
    }
    public static void Log(FormattableString s)
    { 
        Console.WriteLine("It's an interpolated string");
    }
}

However, both these calls are directed at the string overload:

Logger.Log("1 string"); // => "It's a string"
Logger.Log($"{1+1} interpolated string"); // => "It's a string"

If I explicitly cast the interpolated string, it works.

Logger.Log((FormattableString)$"{1+1} interpolated string"); // => "It's an interpolated string"

Is there any way to get the FormattableString overload be called for the interpolated string, without having to add casts everywhere?

For a bit of context:

The logger must run without ever throwing exceptions.

In case of very high memory pressure, even an interpolated string (or rather, its materialization to a normal string) can throw OutOfMemoryException, because under the covers it calls string.Format() which uses a StringBuilder which does memory allocations:

var s = $"this is {1+1} interpolated"; //can throw OOM!

Calls looking like this must not throw:

Logger.Log($"interpolated {1+1}");

...so the materialization of the interpolated string must be deferred and handled inside the logger, and any exceptions swallowed.

like image 553
Cristian Diaconescu Avatar asked Dec 05 '25 20:12

Cristian Diaconescu


1 Answers

You need to introduce a different type with an implicit conversion from string, pls use like this:

class Logger
    {
        public static void Log(String2 s)
        {
            Console.WriteLine("It's a string");
        }
        public static void Log(FormattableString s)
        {
            Console.WriteLine("It's an interpolated string");
        }

    }

    public class String2
    {
        public string Value { get; }

        private String2(string str)
        {
            Value = str;
        }

        public static implicit operator String2(string str)
        {
            return new String2(str);
        }
        public static implicit operator String2(FormattableString formattable)
        {
            return new String2(formattable.ToString());
        }
    }

Result,

First case:

enter image description here

Second case: enter image description here

like image 65
Mansur Qurtov Avatar answered Dec 08 '25 09:12

Mansur Qurtov