Skip to content

[API Proposal]: StringValues implicit conversion to string?[]? causes confusing error with Logging methods #78241

Open
@Jay-Madden

Description

@Jay-Madden

Background and motivation

Background and Motivation

Attempting to log a header value from Headers.TryGetValue in c#11 wont compile due to StringValues

This causes a rather nasty error with logging. Take this code

if (_httpContextAccessor.HttpContext!.Request.Headers.TryGetValue("Origin", out var origin))
{
    _logger.LogInformation("Site Login Request Initialized from Url: {Origin}", origin);
}

Origin will error here with error Possible null reference argument for parameter 'args' in 'Microsoft.Extensions.Logging.LoggerExtensions

Because of the implicit conversion to string?[]? here due to logging methods taking a params object[ as an argument:

public static implicit operator string?[]? (StringValues value)

but that cause is incredibly non obvious.

API Proposal

Not 100% sure what a good design for this is, but the current ergonomics are incredibly unpleasant. Having a struct that can represent null but implicitly converts to a ref type when targeting object/string is quite annoying.

Perhaps an implicit conversion to an empty array for conversions to a non nullable object array.

        public static implicit operator object?[] (StringValues value)
        {
            return value.GetArrayValue() ?? new object[]{};
        }

Just throwing something out there, this has its own problems

API Usage

Same as current, just different overload selected what passed to logging methods

Alternative Designs

A named method could be a decent compromise here, while still a breaking change at least its visible.

public object?[] AsStringArrayOrEmpty(StringValues value)
{
    value.GetArrayValue() ?? Array.Empty<Object>();
}

Risks

Changing representations from null to empty array for specific conversions has the obvious implications of being a breaking change where the implicit null is a relied upon implementation detail.

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions