Description
Description
I was testing out the new config source generator. In .NET Preview 3, I can add the NuGet package to a .NET 7 app, and the app can build and use the source generated code as expected.
With the preview 4 version of the generator I get a compiler error:
error CS8030: Anonymous function converted to a void returning delegate cannot return a value
Reproduction Steps
Program.cs
var builder = WebApplication.CreateBuilder(args);
builder.Services.Configure<TestOptions>(builder.Configuration);
csproj
<Project Sdk="Microsoft.NET.Sdk.Web">
<PropertyGroup>
<TargetFramework>net7.0</TargetFramework>
<Nullable>enable</Nullable>
<!-- 👇 Note that this is required, otherwise it can't find Dictionary<> values-->
<!-- 👇 Should be fixed too 😉-->
<ImplicitUsings>enable</ImplicitUsings>
<LangVersion>latest</LangVersion>
<EnableConfigurationBindingGenerator>true</EnableConfigurationBindingGenerator>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.Extensions.Configuration.Binder" Version="8.0.0-preview.4.*" />
</ItemGroup>
</Project>
Building gives the following error:
CS8030: Anonymous function converted to a void returning delegate cannot return a value
The generated code looks like this (error location highlighted):
// <auto-generated/>
#nullable enable
internal static class GeneratedConfigurationBinder
{
public static global::Microsoft.Extensions.DependencyInjection.IServiceCollection Configure<T>(this global::Microsoft.Extensions.DependencyInjection.IServiceCollection services, global::Microsoft.Extensions.Configuration.IConfiguration configuration)
{
if (configuration is null)
{
throw new global::System.ArgumentNullException(nameof(configuration));
}
if (typeof(T) == typeof(global::TestOptions))
{
return services.Configure<global::TestOptions>(obj =>
{
if (!global::Microsoft.Extensions.Configuration.Binder.SourceGeneration.Helpers.HasValueOrChildren(configuration))
{
// 👇 Anonymous function converted to a void returning delegate cannot return a value
return default;
}
global::Microsoft.Extensions.Configuration.Binder.SourceGeneration.Helpers.BindCore(configuration, ref obj);
});
}
throw new global::System.NotSupportedException($"Unable to bind to type '{typeof(T)}': 'Generator parser did not detect the type as input'");
}
}
namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration
{
using System;
using System.Globalization;
using Microsoft.Extensions.Configuration;
internal static class Helpers
{
public static void BindCore(IConfiguration configuration, ref TestOptions obj)
{
if (obj is null)
{
throw new ArgumentNullException(nameof(obj));
}
if (configuration["String"] is string stringValue1)
{
obj.String = stringValue1;
}
}
public static bool HasValueOrChildren(IConfiguration configuration)
{
if ((configuration as IConfigurationSection)?.Value is not null)
{
return true;
}
return HasChildren(configuration);
}
public static bool HasChildren(IConfiguration configuration)
{
foreach (IConfigurationSection section in configuration.GetChildren())
{
return true;
}
return false;
}
}
}
Expected behavior
No build errors. With preview 3 there are no build errors, because it's not returning a value. This is the generated code using the preview 3 package:
// <auto-generated/>
#nullable enable
using System.Linq;
internal static class GeneratedConfigurationBinder
{
public static global::Microsoft.Extensions.DependencyInjection.IServiceCollection Configure<T>(this global::Microsoft.Extensions.DependencyInjection.IServiceCollection services, global::Microsoft.Extensions.Configuration.IConfiguration configuration)
{
if (typeof(T) == typeof(TestOptions))
{
return services.Configure<TestOptions>(obj =>
{
BindCore(configuration, ref obj);
});
}
throw new global::System.NotSupportedException($"Unable to bind to type '{typeof(T)}': 'Generator parser did not detect the type as input'");
}
private static void BindCore(global::Microsoft.Extensions.Configuration.IConfiguration configuration, ref TestOptions obj)
{
if (obj is null)
{
throw new global::System.ArgumentNullException(nameof(obj));
}
if (configuration["String"] is string stringValue1)
{
obj.String = stringValue1;
}
}
public static bool HasChildren(global::Microsoft.Extensions.Configuration.IConfiguration configuration)
{
foreach (global::Microsoft.Extensions.Configuration.IConfigurationSection section in configuration.GetChildren())
{
return true;
}
return false;
}
}
``
### Actual behavior
error CS8030: Anonymous function converted to a void returning delegate cannot return a value
### Regression?
Yes, this worked in the .NET 8 preview 3 Microsoft.Extensions.Configuration.Binder package (tested with .NET 7)
### Known Workarounds
_No response_
### Configuration
.NET SDK:
Version: 7.0.202
Commit: 6c74320bc3
Runtime Environment:
OS Name: Windows
OS Version: 10.0.19044
OS Platform: Windows
RID: win10-x64
Base Path: C:\Program Files\dotnet\sdk\7.0.202\
Host:
Version: 7.0.5
Architecture: x64
Commit: 8042d61
Not tested on anything else yet
### Other information
_No response_