首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >为什么VB.Net不能在接口上找到扩展方法?

为什么VB.Net不能在接口上找到扩展方法?
EN

Stack Overflow用户
提问于 2012-05-31 08:03:40
回答 4查看 2.8K关注 0票数 5

我有一个C#库,它有一个扩展方法,类似于:

代码语言:javascript
复制
public interface ISomething { ... }
public class SomethingA : ISomething { ... }
public class SomethingB : ISomething { ... }

public static class SomethingExtensions 
{
    public static int ExtensionMethod(this ISomething input, string extra) 
    {
    }
}

如果从C#调用,则扩展可以正常工作,但如果从外部VB.Net应用程序调用,则会出现问题:

代码语言:javascript
复制
Dim something = Me.SomethingManager.GetSomething(key)
Dim result = something.ExtensionMethod("extra")

这可以很好地编译,但在运行时抛出一个异常:

未找到“SomethingB”类型上的公共成员“SomethingB”。

如果将VB.Net更改为显式地使该类型成为接口,则它可以工作:

代码语言:javascript
复制
Dim something as ISomething = Me.SomethingManager.GetSomething(key)
Dim result = something.ExtensionMethod("extra")

为什么?为什么扩展方法在接口上工作,而不是在实现它的类上工作?如果我使用子类,我会有同样的问题吗?VB.Net的扩展方法实现是否不完整?

在C#库中有什么可以让VB.Net在没有显式接口的情况下工作吗?

EN

回答 4

Stack Overflow用户

回答已采纳

发布于 2012-05-31 13:11:19

根据选项推断,这段代码..。

代码语言:javascript
复制
Dim something = Me.SomethingManager.GetSomething(key)
Dim result = something.ExtensionMethod("extra")

...is和.

代码语言:javascript
复制
Dim something As Object = Me.SomethingManager.GetSomething(key)
Dim result As Object = something.ExtensionMethod("extra")

因为somethingObject类型的,所以它找不到扩展方法,因为它不是在Object类型上定义的。

现在,如果设置Option Infer On,您将获得与C#的var关键字相同的结果。类型将自动推断。注意,这也可能破坏现有代码,但可以为特定文件(如Option Strict )启用它。

最佳实践是将Option StrictOption Infer设置为On。

票数 5
EN

Stack Overflow用户

发布于 2012-05-31 08:06:30

如果它抛出一个异常,而不是提供编译时错误,那就意味着您已经删除了选项严格 .我不知道在这种情况下扩展方法会发生什么,因为它们通常是在编译时解析的,但是在选项严格关闭的情况下,已经开始了后期绑定。

我建议你严格选择,一切都会好的.

(您还需要导入名称空间,按照Richard的回答,但我认为您已经这样做了。无论如何,如果您忘记在打开选项后执行该操作,您将看到编译时错误。

票数 1
EN

Stack Overflow用户

发布于 2012-05-31 11:13:45

感谢乔恩为我指明了正确的方向,但这里已经足够了,需要一个完整的答案。

扩展方法是一个编译器技巧,所以(在C#中):

代码语言:javascript
复制
var something = this.SomethingManager.GetSomething(key);
var result = something.ExtensionMethod("extra");

在编译时转换为:

代码语言:javascript
复制
ISomething something = this.SomethingManager.GetSomething(key);
int result = SomethingExtensions.ExtensionMethod(something, "extra");

作为类的一种方法出现的静态扩展方法只是编译器的聪明。

问题是VB中的Dim与C#中的var不一样。感谢VB的后期绑定,它更接近于dynamic

因此,使用VB中的原始示例:

代码语言:javascript
复制
Dim something = Me.SomethingManager.GetSomething(key)
Dim result = something.ExtensionMethod("extra")

与C#不同的是,在VB中,something的类型一直保留到运行时,使扩展方法正常工作的编译器聪明无法实现。如果显式声明了该类型,则可以解析扩展方法,但是如果后期绑定,则扩展方法永远无法工作。

如果他们使用Option Strict On (就像Jon建议的那样),那么他们就不得不总是声明类型,早期绑定就会发生,编译器的聪明使得扩展方法能够工作。这是最好的实践,但由于他们还没有这么做,这对他们来说将是一个痛苦的改变。

这个故事的寓意是:不要在API中使用扩展方法,如果你期望VB中的任何人靠近它:-S

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/10829615

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档