Skip to content

The 'string' operator produces suboptimal code when the object's type is known. #9153

Closed
@teo-tsirpanis

Description

@teo-tsirpanis

This simple code snippet:

let f() = string 4

produces this IL code that involves a redundant boxing and type checking:

public static string f()
{
    object obj = 4;
    if (obj != null)
    {
        IFormattable formattable = obj as IFormattable;
        if (formattable != null)
        {
            IFormattable formattable2 = formattable;
            return formattable2.ToString(null, CultureInfo.InvariantCulture);
        }
        object obj2 = obj;
        return obj2.ToString();
    }
    return "";
}

The compiler knows that 4 is an integer and implements IFormattable. For value types and sealed classes known to implement it, emitting a direct call to ToString with the invariant culture passed (and the constrained. IL prefix) would be much better. Same with the eligible types that are known to not implement it.

For all other cases (non-sealed reference types that do not implement IFormattable), the existing behavior is acceptable (no boxings) and backwards-compatible. Performance-concerned developers can always directly call ToString().

There might be a problem with types that might stop implementing IFormattable at a later version of the library, but this is a breaking change that should require recompilation and we should not be concerned with such scenarios.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions