我有一个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'上的公共成员'ExtensionMethod'。
如果改变VB.Net以明确地使类型成为它工作的接口:
Dim something as ISomething = Me.SomethingManager.GetSomething(key)
Dim result = something.ExtensionMethod("extra")
为什么呢?为什么扩展方法适用于接口而不是实现它的类?如果我使用子类,我会遇到同样的问题吗? VB.Net的扩展方法实现是否不完整?
我可以在C#库中做些什么来使VB.Net在没有显式接口的情况下工作?
答案 0 :(得分:4)
使用Option Infer Off,此代码......
Dim something = Me.SomethingManager.GetSomething(key)
Dim result = something.ExtensionMethod("extra")
...与...相同
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
都设置为开启。
答案 1 :(得分:1)
如果抛出异常而不是发出编译时错误,那表明你已经关闭Option Strict ...我不知道扩展方法会发生什么变化那种情况,因为它们通常在编译时解决,但是如果Option Strict关闭,你就会有后期绑定。
我建议你打开Option Strict,一切都应该好......
(根据Richard的回答,你还需要导入命名空间,但我认为你已经完成了。你会看到编译时< / em>错误,如果您在关闭选项严格后忘记执行此操作。无论如何。)
答案 2 :(得分:1)
为乔恩指责我指向正确的方向干杯,但这里有足够的答案需要一个完整的答案。
扩展方法是编译技巧,所以(在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建议的那样)那么他们就会被迫总是声明类型,早期绑定发生,编译器的聪明才能使扩展方法起作用。无论如何,这是最好的做法,但由于他们没有这样做,这对他们来说将是一个痛苦的变化。
这个故事的寓意:如果你希望VB附近有人在你的API附近使用扩展方法:-S
答案 3 :(得分:0)
您是否导入了包含定义命名空间的类的命名空间。
EG。没有
,你将看不到任何LINQ to Objects扩展方法Imports System.Linq