如何在VB代码中调用C#扩展方法

我有一个类库,其中包含一些用C#编写的扩展方法和一个用VB编写的旧网站。

我想从VB代码中调用我的扩展方法,但它们没有出现在intelisense中,当我访问该站点时出现编译错误。

我已经获得了所有必需的Import,因为同一名称空间中包含的其他类在Intelisense中看起来很好。

有什么建议

编辑:更多信息,以帮助一些评论。

我的实现看起来像这样

//C# code compiled as DLL namespace xy { public static class z { public static string q (this string s){ return s + " " + s; } } } 

和我这样的用法

 Imports xy '...' Dim r as string = "greg" Dim s as string = rq() ' does not show in intelisense ' and throws error : Compiler Error Message: BC30203: Identifier expected. 

它适用于我,虽然有一些怪癖。 首先,我创建了一个面向.NET 3.5的C#类库。 这是项目中唯一的代码:

 using System; namespace ExtensionLibrary { public static class Extensions { public static string CustomExtension(this string text) { char[] chars = text.ToCharArray(); Array.Reverse(chars); return new string(chars); } } } 

然后我创建了一个面向.NET 3.5的VB控制台应用程序,并添加了对我的C#项目的引用。 我将Module1.vb重命名为Test.vb,这是代码:

 Imports ExtensionLibrary Module Test Sub Main() Console.WriteLine("Hello".CustomExtension()) End Sub End Module 

这编译并运行。 (我本来会调用方法Reverse()但是我不确定VB是否可能在某处已经神奇地具有反向能力 – 我不是一个长期粉笔的VB专家。)

最初,我没有提供ExtensionLibrary作为Intellisense的导入。 即使在构建之后,“Imports ExtensionLibrary”也会变灰,并且灯泡提供了删除所谓冗余导入的机会。 (这样做会破坏项目。)请注意,这可能是ReSharper而不是Visual Studio。

所以简而言之,可以做到,它应该可以正常工作。 我不认为问题是你要么使用旧版本的VB,要么你的项目不是针对.NET 3.5?

如注释中所述:还有一个额外的怪癖,即当目标的编译时类型为Object时,将找不到扩展方法 。

扩展方法只是静态方法的语法糖。 所以

 public static string MyExtMethod(this string s) 

可以在VB.NET和C#中调用

 MyExtMethod("myArgument") 

好。 根据错误消息,您肯定没有使用最新的VB版本(VB 9!)或错误与此问题无关,因为如果找不到该方法,您将收到另一个错误:

错误1’q’不是’String’的成员。

 Imports xy '...' Dim r As String = "greg" Dim s As String = rq() 'same as zq(r) 

我想我遇到了类似的问题 :VB.Net非常乐意通过扩展方法进行编译,如果Option Strict关闭,可以在运行时进行推断。

但是,VB.Net似乎并不喜欢基本类型的扩展方法。 如果您执行以下操作,则无法扩展Object并且无法解析它:

C#

 namespace NS ... public static class Utility { public static void Something(this object input) { ... public static void Something(this string input) { ... } // Works fine, resolves to 2nd method "test".Something(); // At compile time C# converts the above to: Utility.Something("test"); 

但是这在VB.Net中出错了:

 Option Infer On Option Explicit On Option Strict Off Imports NS ... Dim r as String = "test" r.Something() 

编译没有错误,但在运行时失败,因为Something不是String的方法 – 编译器无法用对Utility.Something的静态调用替换扩展方法的语法糖。

问题是为什么? 与C#不同, VB.Net无法处理Object任何扩展 ! C#中的有效扩展方法会混淆VB.Net编译器。

作为一般的VB.Net规则,我避免使用任何基本.Net类型( ObjectStringInteger等)的扩展方法。 您还必须小心使用Option Infer VBCodeProvider ,因为默认情况下它在Visual Studio中处于打开状态,默认情况下,命令行编译, VBCodeProvider以及可能在网站中(取决于您的web.config)。 当它关闭时,VB.Net中的所有内容都被认为是一个Object ,所有扩展方法都将被保留到运行时(因此会失败)。

我认为微软在向VB.Net添加扩展方法时真的放弃了它,我认为这是尝试(并且失败)使其与C#保持一致的事后想法。

我不知道你是否可以用与C#中相同的点符号来调用它们,但我认为静态扩展方法将显示为静态函数,其中第一个参数为扩展类型。 所以你应该能够用VB调用实际的类:

 StaticClass.ExtensionMethod(theString, arg1, ..., argN) 

您在C#中的位置刚刚写完:

 theString.ExtensionMethod(arg1, ..., argN); 

StaticClass是您在其中定义扩展方法的静态类的名称。

……还有一个用VB编写的旧网站。

这里的“旧”是否意味着您也可以在这里使用旧版本的VB? 无论如何,由于扩展方法只是用属性修饰的vanilla static(“ Shared ”)方法,因此您应该能够在任何情况下调用它们。

如果这是不可能的,你可以尝试在旧版本的VB中将它们称为“扩展样式”,或者引用错误版本的C#程序集。

编辑:你确定要Import 整个命名空间,即xy而不只是x吗? VB能够比C#更容易地访问嵌套命名空间,因此您可以使用VB中的以下代码来使用命名空间xy中的类。 但是,要使扩展方法起作用,必须Import 完整路径。

 Imports x Dim x As New y.SomeClass() 

要检查两件事:

  1. 你是针对.Net 3.5
  2. 您正在引用DLL

某些工具可能会错误地为不支持它们的项目建议扩展方法。

我遇到了同样的问题,可能偶然发现了解决方案。 如果我用过

 xyrq() 

,它也给我带来了同样的错误。 但是,如果我导入xy,它可以工作,所以:

 using xy; ... rq() 

很好。

所以显然你必须在声明中导入它才能使它工作。

这是很久以前我不能真正解决它,但不用说,这是用户错误。 我可能重新启动了我的计算机并将其移走了。