1

Consider this code - two extension methods for an interface - one generic and one is not. This code is imported with a library AutoFixture and cannot be changed.

public interface IFixture
{
}

public static class FixtureFreezer
{
    //this is a real method within AutoFixture. The code is simplified though
    public static T Freeze<T>(this IFixture fixture) where T:new()
    {
        return new T();
    }

    //not a real method, added for test
    public static int Foo(this IFixture fixture)
    {
        return 0;
    }
}

Now I wanted to create an overload for Freeze<T>. However this results in a recursive call - fixture.Freeze<T>() uses the params overload with empty array as params and not the parameterless overload.

public static class FixtureExtensions
{
    public static T Freeze<T>(this IFixture fixture, params object[] arguments)
    {
        // do something
        return fixture.Freeze<T>(); //recursion
    }
    public static int Foo(this IFixture fixture, params object[] arguments)
    {
        return fixture.Foo(); //no recursion
    }
}

I have created the non-generic Foo method for test and it is correctly resolved.

Is this behaviour correct? Can I somehow call the parameterless overload inside of my overload with params?


NOTE The simplified version does not reflect the real situation. To reproduce the problem please download AutoFixture.

Rasmond
  • 442
  • 4
  • 15
  • 1
    Does behavior change if you add the `where T:new()` constraint in `FixtureExtions`'s `Freeze` ? – Fildor Oct 26 '21 at 08:41
  • @Fildor yeah it probably would, nice call – TheGeneral Oct 26 '21 at 08:42
  • well, resolving extension-methods is done recursivly starting at your class you're currently in, which is your extension-class. As there already is a match, why search any further? Just searching for the dupe... – MakePeaceGreatAgain Oct 26 '21 at 08:43
  • @Fildor it does in my simplified version, it doesn't in a real scenario. I will try to update the simplified version – Rasmond Oct 26 '21 at 08:44
  • @TheGeneral Thanks. I was actually just _guessing_ that the compiler needs the type argument to have the same constraints for the match. – Fildor Oct 26 '21 at 08:44
  • @HimBromBeere I am not sure if that dupe applies here. The dupe question was about a signature-identical extension to a Linq extension. These above have different parameter sets ... – Fildor Oct 26 '21 at 08:49
  • @Fildor From Jons answer: "It will stop as soon as it finds any eligible extension methods" So I suppose that applies to all candidates. So searching stops as soon as a match was found. – MakePeaceGreatAgain Oct 26 '21 at 08:51
  • 1
    Perhaps `if (arguments.Length == 0) { return FixtureFreezer.Freeze(fixture); }` in `FixtureExtensions` would solve it for you? – ProgrammingLlama Oct 26 '21 at 08:55
  • @HimBromBeere I am running some probe now. It seems you are right, as long as one of the extension classes are not in the same namespace as the extended class itself. Which is basically, what Jon is sayin, too - am I right? – Fildor Oct 26 '21 at 08:56
  • @Llama perfect <3 this is the solution – Rasmond Oct 26 '21 at 08:57

0 Answers0