Reputation: 33048
I'm wondering about the behavior of extension methods in C#. Please see the examples below:
static string ExtendedToString( this object oObj )
{
return "Object";
}
static string ExtendedToString( this Array oArray )
{
return "Array";
}
// Example 1: int array - working as expected.
int[] o = new int[] { 1, 2, 3 };
o.ExtendedToString( ); // returns "Array"
// Example 2: array as object - did not expect the result.
object o = new int[] { 1, 2, 3 };
o.ExtendedToString( ); // returns "Object"
Why is (in the last case) the object's extension method called and not the one for int[]?
Upvotes: 1
Views: 581
Reputation: 108790
Thomas Levesque already has a perfect explanation of why your code doesn't work, so I won't repeat that. The work around is testing at runtime with is
or as
:
static string ExtendedToString( this object oObj )
{
if(oObj is Array)
return "Array";
else
return "Object";
}
Generally type testing in such a way is a bit of an anti-pattern and you should prefer virtual methods where possible. But in this case it's probably still the best solution since you can't change the Array/Object classes.
If there are many classes which need special treatment you could consider a Type
-> Func<object,string>
Dictionary.
Upvotes: 0
Reputation: 39491
Because of static typing. Extension methods are rewrited by compiler as if you called them by regular syntax. At the compile time, second object o has the type of Object, so object's extension method is called
Upvotes: 1
Reputation: 292355
Overload resolution is performed at compile time. The compiler sees that o
is declared as object
, so it calls the overload that takes an object
. The fact that o
actually contains an array at runtime is irrelevant, because the compiler doesn't know it.
That's actually not specific to extension methods, you would get the same result by calling it as a normal static method (ExtensionsClass.ExtendedToString(o)
)
Upvotes: 9
Reputation: 6526
You declared o as object:
object o = new int[] { 1, 2, 3 };
thats why:
o.ExtendedToString( ); // returns "Object"
but you can
int[] obj = o as int[];
obj.ExtendedToString( ); // returns "Array"
as the resolution is depending on the (static) type
Upvotes: 1