C#扩展方法无法按预期工作 - 请参阅示例

时间:2011-04-06 07:53:56

标签: c# .net extension-methods

我想知道C#中扩展方法的行为。请参阅以下示例:

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"

为什么(在最后一种情况下)调用了对象的扩展方法而不是int []?

4 个答案:

答案 0 :(得分:9)

重载分辨率在编译时执行。编译器看到o被声明为object,因此它调用带有object的重载。 o实际上在运行时包含数组的事实是无关紧要的,因为编译器不知道它。

这实际上并不特定于扩展方法,通过将其称为普通静态方法(ExtensionsClass.ExtendedToString(o))来获得相同的结果

答案 1 :(得分:1)

您将o声明为对象:

object o = new int[] { 1, 2, 3 };

这就是为什么:

o.ExtendedToString( ); // returns "Object"

但你可以

int[] obj = o as int[];
obj.ExtendedToString( ); // returns "Array"

因为分辨率取决于(静态)类型

答案 2 :(得分:1)

由于静态输入。扩展方法由编译器重写,就像您通过常规语法调用它们一样。在编译时,第二个对象o具有Object类型,因此对象的扩展方法称为

答案 3 :(得分:0)

托马斯·莱维斯克已经对你的代码无效的原因有了完美的解释,所以我不再重复了。解决方法是在运行时使用isas

进行测试
static string ExtendedToString( this object oObj )
{
    if(oObj is Array)
        return "Array";
    else
        return "Object";
}

通常,以这种方式进行类型测试有点反模式,您应该尽可能选择虚方法。但在这种情况下,它可能仍然是最佳解决方案,因为您无法更改Array / Object类。

如果有许多课程需要特殊处理,您可以考虑Type - &gt; Func<object,string>字典。