Skip to content

C# 9 => C# 10 upgrade causing CS0411 with an extension method #57630

@bradwilson

Description

@bradwilson

Version Used: C# 10 (upgrading from C# 9)

Steps to Reproduce:

I have the following definition of a dictionary:

delegate void PropertyWriter(Utf8JsonWriter writer, object? value, JsonSerializerOptions options);

static readonly Dictionary<Type, PropertyWriter> propertyWriters = new();

I have the following extension method:

public static TValue GetOrAdd<TKey, TValue>(
	this IDictionary<TKey, TValue> dictionary,
	TKey key,
	Func<TValue> newValue)
		where TKey : notnull
{
	Guard.ArgumentNotNull(nameof(dictionary), dictionary);
	Guard.ArgumentNotNull(nameof(key), key);
	Guard.ArgumentNotNull(nameof(newValue), newValue);

	if (!dictionary.TryGetValue(key, out var result))
	{
		result = newValue();
		dictionary[key] = result;
	}

	return result;
}

I have the following code calling the extension method:

propertyWriters.GetOrAdd(propertyType, () =>
{
	var converter = jsonSerializerOptions.GetConverter(propertyType);
	if (converter == null)
		throw new InvalidOperationException($"Could not find serializer for {propertyType.FullName}");

	var writeMethod =
		converter
			.GetType()
			.GetMethods()
			.Where(mi =>
			{
				if (mi.Name != "Write")
					return false;
				var parameters = mi.GetParameters();
				return parameters.Length == 3
					&& parameters[0].ParameterType == typeof(Utf8JsonWriter)
					&& parameters[2].ParameterType == typeof(JsonSerializerOptions);
			})
			.SingleOrDefault();

	if (writeMethod == null)
		throw new InvalidOperationException($"Could not find Write method on '{converter.GetType().FullName}' to serialize '{propertyType.FullName}'");

	return (Utf8JsonWriter writer, object? value, JsonSerializerOptions options) =>
		writeMethod.Invoke(converter, new object?[] { writer, value, options });
});

Expected Behavior:

In C# 9, this code compiles as expected.

Actual Behavior:

In C# 10, I get the following error:

error CS0411: The type arguments for method 'DictionaryExtensions.GetOrAdd<TKey, TValue>(IDictionary<TKey, TValue>, TKey, Func<TValue>)' cannot be inferred from the usage. Try specifying the type arguments explicitly.

Interestingly, the tooltip in VS 2022 correctly resolves the type arguments while also showing me the error:

Adding the explicit type arguments to the GetOrAdd call does work as expected, but should be unnecessary.

Also worth noting that I have 7 invocations of this extension method, but this is the only one that no longer compiles. It is the only one that's storing a delegate as the dictionary value (the others are storing simple values), so that may have something to do with it.

Metadata

Metadata

Assignees

Type

No type
No fields configured for issues without a type.

Projects

No projects

Milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions