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

发布于 2024-10-30 16:15:43 字数 519 浏览 4 评论 0原文

我想知道 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[] 的扩展方法?

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[]?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

好菇凉咱不稀罕他 2024-11-06 16:15:43

重载解析是在编译时执行的。编译器发现 o 被声明为 object,因此它调用采用 object 的重载。 o 在运行时实际上包含一个数组这一事实是无关紧要的,因为编译器不知道它。

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

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))

生活了然无味 2024-11-06 16:15:43

您将 o 声明为对象:

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

这就是原因:

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

但是您可以,

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

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

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

以歌曲疗慰 2024-11-06 16:15:43

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

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

屋檐 2024-11-06 16:15:43

Thomas Levesque 已经对为什么你的代码不起作用有一个完美的解释,所以我不会重复。解决方法是在运行时使用 isas 进行测试:

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

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

如果有许多类需要特殊处理,您可以考虑 Type -> Func 字典。

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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文