Używając .NET 4, jestem zdezorientowany przez niezdolność kompilatora do rozwiązania pierwszego wywołania metody w poniższym przykładzie.Problem z rozdzielczością metody z domyślnymi parametrami i generycznymi
using System;
namespace MethodResolutionTest
{
class Program
{
static void Main(string[] args)
{
NonGeneric foo = null;
// ambiguous
foo.Ext1(x => new NonGeneric());
// resolves to first Ext1
foo.Ext1(x => new NonGeneric(), 1);
// resolves to first Ext2
foo.Ext2(x => new NonGeneric());
// resolves to first Ext2
foo.Ext2(x => new NonGeneric(), 1);
// resolves to second Ext2
foo.Ext2(x => "foo");
// resolves to second Ext2
foo.Ext2(x => "foo", 1);
// resolves to first Ext3
foo.Ext3(x => new NonGeneric());
// resolves to first Ext3
foo.Ext3(x => new NonGeneric(), 1);
// resolves to second Ext3
foo.Ext3(x => "foo");
// resolves to second Ext3
foo.Ext3(x => "foo", 1);
}
}
public class NonGeneric
{
}
public class Generic<T> : NonGeneric
{
}
public static class Extensions1
{
public static NonGeneric Ext1(this NonGeneric first, Func<NonGeneric, NonGeneric> getNext, int i = 0)
{
return null;
}
public static Generic<TNext> Ext1<TNext>(this NonGeneric first, Func<NonGeneric, TNext> getNext, int i = 0, string s = null)
{
return null;
}
}
// only difference between Extensions2 and Extensions1 is that the second overload no longer has a default string parameter
public static class Extensions2
{
public static NonGeneric Ext2(this NonGeneric first, Func<NonGeneric, NonGeneric> getNext, int i = 0)
{
return null;
}
public static Generic<TNext> Ext2<TNext>(this NonGeneric first, Func<NonGeneric, TNext> getNext, int i = 0)
{
return null;
}
}
// Extensions3 explicitly defines an overload that does not default the int parameter
public static class Extensions3
{
public static NonGeneric Ext3(this NonGeneric first, Func<NonGeneric, NonGeneric> getNext)
{
return Ext3(first, getNext, default(int));
}
public static NonGeneric Ext3(this NonGeneric first, Func<NonGeneric, NonGeneric> getNext, int i = 0)
{
return null;
}
public static Generic<TNext> Ext3<TNext>(this NonGeneric first, Func<NonGeneric, TNext> getNext, int i = 0)
{
return null;
}
}
}
Czy ktoś może rzucić trochę światła na to? Podejrzewam, że nie mam tutaj innej drogi niż modyfikowanie moich interfejsów API, aby pomóc kompilatorowi (jak na Extensions3
powyżej), ale jeśli jest łatwiejszy/lepszy sposób, to chciałbym to usłyszeć.
Kompilator wybiera dobrze w obu '' Extensions3' Extensions2' i scenariuszy, więc nie jest to tak proste. Ponadto, jeśli nie chcę domyślnego parametru 'int', to oczywiście nie zadeklarowałbym tego w ten sposób! –
Ale dlaczego masz dwie metody z opcjonalnymi parametrami, które są skutecznie niejednoznaczne, jeśli pominięto opcjonalne parametry? Jeśli absolutnie ** potrzebujesz ** obu metod, będziesz musiał użyć albo 'Extensions2' lub' Extensions3'. – khellang
@khellang: czy możesz wskazać sekcje specyfikacji języka C# prowadzące do takiego zachowania (niejednoznaczność rozdzielczości przeciążania)? –