Description
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:
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.