我有一个C#库,它有一个扩展方法,类似于:
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应用程序调用,则会出现问题:
Dim something = Me.SomethingManager.GetSomething(key)
Dim result = something.ExtensionMethod("extra")这可以很好地编译,但在运行时抛出一个异常:
未找到“SomethingB”类型上的公共成员“SomethingB”。
如果将VB.Net更改为显式地使该类型成为接口,则它可以工作:
Dim something as ISomething = Me.SomethingManager.GetSomething(key)
Dim result = something.ExtensionMethod("extra")为什么?为什么扩展方法在接口上工作,而不是在实现它的类上工作?如果我使用子类,我会有同样的问题吗?VB.Net的扩展方法实现是否不完整?
在C#库中有什么可以让VB.Net在没有显式接口的情况下工作吗?
发布于 2012-05-31 13:11:19
根据选项推断,这段代码..。
Dim something = Me.SomethingManager.GetSomething(key)
Dim result = something.ExtensionMethod("extra")...is和.
Dim something As Object = Me.SomethingManager.GetSomething(key)
Dim result As Object = something.ExtensionMethod("extra")因为something是Object类型的,所以它找不到扩展方法,因为它不是在Object类型上定义的。
现在,如果设置Option Infer On,您将获得与C#的var关键字相同的结果。类型将自动推断。注意,这也可能破坏现有代码,但可以为特定文件(如Option Strict )启用它。
最佳实践是将Option Strict和Option Infer设置为On。
发布于 2012-05-31 08:06:30
如果它抛出一个异常,而不是提供编译时错误,那就意味着您已经删除了选项严格 .我不知道在这种情况下扩展方法会发生什么,因为它们通常是在编译时解析的,但是在选项严格关闭的情况下,已经开始了后期绑定。
我建议你严格选择,一切都会好的.
(您还需要导入名称空间,按照Richard的回答,但我认为您已经这样做了。无论如何,如果您忘记在打开选项后执行该操作,您将看到编译时错误。
发布于 2012-05-31 11:13:45
感谢乔恩为我指明了正确的方向,但这里已经足够了,需要一个完整的答案。
扩展方法是一个编译器技巧,所以(在C#中):
var something = this.SomethingManager.GetSomething(key);
var result = something.ExtensionMethod("extra");在编译时转换为:
ISomething something = this.SomethingManager.GetSomething(key);
int result = SomethingExtensions.ExtensionMethod(something, "extra");作为类的一种方法出现的静态扩展方法只是编译器的聪明。
问题是VB中的Dim与C#中的var不一样。感谢VB的后期绑定,它更接近于dynamic。
因此,使用VB中的原始示例:
Dim something = Me.SomethingManager.GetSomething(key)
Dim result = something.ExtensionMethod("extra")与C#不同的是,在VB中,something的类型一直保留到运行时,使扩展方法正常工作的编译器聪明无法实现。如果显式声明了该类型,则可以解析扩展方法,但是如果后期绑定,则扩展方法永远无法工作。
如果他们使用Option Strict On (就像Jon建议的那样),那么他们就不得不总是声明类型,早期绑定就会发生,编译器的聪明使得扩展方法能够工作。这是最好的实践,但由于他们还没有这么做,这对他们来说将是一个痛苦的改变。
这个故事的寓意是:不要在API中使用扩展方法,如果你期望VB中的任何人靠近它:-S
https://stackoverflow.com/questions/10829615
复制相似问题