Reputation: 16067
I have an extension method that works on any class, but I want to call a special version if I am working on IEnumerable<T>
.
For Example
public static class ExtensionMethods
{
public static dynamic Test<T>(this T source)
{
dynamic expandoObject = new System.Dynamic.ExpandoObject();
var dictionary = (IDictionary<string,object>)expandoObject;
dictionary["Test"] = source.ToString();
return dictionary;
}
public static IEnumerable<dynamic> Test<T>(this List<T> source)
{
var result = new List<dynamic>();
foreach(var r in source)
yield return r.Test();
}
public static IEnumerable<dynamic> Test<T>(this IEnumerable<T> source)
{
var result = new List<dynamic>();
foreach(var r in source)
yield return r.Test();
}
}
// Usage
public class X
{
string guid = Guid.NewGuid().ToString();
}
void Main()
{
List<X> list = new List<X>() { new X() };
list.Test().Dump(); // Correct but only works because there is an explicit overload for List<T>
var array = list.ToArray();
((IEnumerable<X>) array).Test().Dump(); // Correct
array.Test().Dump(); // Calls the wrong extension method
}
Is there any way I can get array.Test() to call the IEnumerable version without having to explicitly cast it?
Alternatively, if I give the extension method different names, if there any way I can get a compiler error if I accidently use the wrong one?
Upvotes: 3
Views: 88
Reputation: 11883
Add this extension method to explicitly catch all array types:
public static IEnumerable<dynamic> Test<T>(this T[] source)
{
var result = new List<dynamic>();
foreach(var r in source)
yield return r.Test();
}
Upvotes: 0
Reputation: 2925
You can specify T
and not rely on type inference, this will hint compiler to use correct extension method. Code would look like this:
var array = list.ToArray();
array.Test<X>().Dump();
What happens is, that compiler cannot tell which extension to use, since Array
is valid argument for both method signatures:
public static dynamic Test<T>(this T source) { .. }
public static IEnumerable<dynamic> Test<T>(this IEnumerable<T> source) { .. }
In first case compiler can assume T
is of type Array
. Because of it, compiler has to picks one (might be first defined?).
Upvotes: 0
Reputation: 13988
I think you are trying to solve it in a wrong direction. The List implements IEnumerable interface and as such the compiler can have problem with solving the best method will be invoked on List. What you could do -- you could test if the IEnumerable is a list inside the extension method.
public static IEnumerable<dynamic> Test<T>(this IEnumerable<T> source)
{
if (source is List<T>) {
// here
}
var result = new List<dynamic>();
foreach(var r in source)
yield return r.Test();
}
Upvotes: 1