Closed
Description
Description
When binding to a property that exposes an ISet with a setter and initializes the property with some collection, that collection is ignored and instead a new HashTable is created. This could change the comparator or otherwise result in different behavior than the pre-allocated collection.
Reproduction Steps
using Configuration.Binder.Working;
using Microsoft.Extensions.Configuration;
IConfiguration config = new ConfigurationBuilder()
.AddInMemoryCollection()
.Build();
config["MySet:0"] = "HelloWorld";
TestObject obj = config.Get<TestObject>()!;
Console.WriteLine($"Test object contains helloworld: {obj.MySet.Contains("helloworld")}");
// workaround
obj.MySet = new HashSet<string>(obj.MySet, StringComparer.OrdinalIgnoreCase);
Console.WriteLine($"Test object contains helloworld: {obj.MySet.Contains("helloworld")}");
public class TestObject
{
public ISet<string> MySet { get; set; } = new HashSet<string>(StringComparer.OrdinalIgnoreCase);
}
Expected behavior
This should succeed, using the user-initialized collection with case insensitive comparer.
Actual behavior
The first call fails because ConfigurationBinder recreated the ISet<string>
as a new HashSet<string>()
using case-sensitive comparer.
Regression?
Yes, from 6.0.0 due to this PR #68133
Known Workarounds
One can recreate the collection after binding.
obj.MySet = new HashSet<string>(obj.MySet, StringComparer.OrdinalIgnoreCase);
Or hide the setter, to prevent ConfigurationBinder from resetting the instance.
Configuration
No response
Other information
No response