如何在VB代码中调用C#扩展方法
-
03-07-2019 - |
题
我有一个类库,其中包含一些用C#编写的扩展方法和一个用VB编写的旧网站。
我想从VB代码调用我的扩展方法,但它们没有出现在intelisense中,当我访问该网站时出现编译错误。
我已经获得了所有必需的 Import ,因为同一名称空间中包含的其他类在Intelisense中显得很好。
任何建议
编辑:有关评论的更多信息。
我的实现看起来像这样
//C# code compiled as DLL
namespace x.y {
public static class z {
public static string q (this string s){
return s + " " + s;
}
}
}
和我这样的用法
Imports x.y
'...'
Dim r as string = "greg"
Dim s as string = r.q() ' 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 x.y
'...'
Dim r As String = "greg"
Dim s As String = r.q() 'same as z.q(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类型的扩展方法( Object
, String
, Integer
等)。您还必须小心使用 Option Infer
,因为它默认情况下在Visual Studio中处于打开状态,默认情况下它对于命令行编译, VBCodeProvider
以及可能在网站中是关闭的(取决于在你的web.config上)。当它关闭时,VB.Net中的所有内容都被认为是 Object
,并且所有扩展方法都将保留到运行时(因此将失败)。
我认为微软在向VB.Net添加扩展方法时真的放弃了它,我认为这是尝试(并且失败)使其与C#保持一致的事后想法。
我不知道你是否可以用与C#中相同的点符号来调用它们,但我认为静态扩展方法会以第一个参数作为扩展类型显示为静态函数。所以你应该能够用VB调用VB中的实际类:
StaticClass.ExtensionMethod(theString, arg1, ..., argN)
在C#中你刚才写的:
theString.ExtensionMethod(arg1, ..., argN);
使用StaticClass作为定义扩展方法的静态类的名称。
…和一个用VB编写的旧网站。
“ old”也许这意味着你也可以在这里使用旧版本的VB?无论如何,因为扩展方法只是用属性装饰的vanilla static(“ Shared
”)方法,所以 应该能够在任何情况下调用它们
如果这是不可能的,你要么试着打电话给他们“扩展风格”在旧版本的VB中,或者您引用了错误版本的C#程序集。
编辑:你确定你是导入
整个命名空间,即 xy
而不只是 x
? VB能够比C#更容易地访问嵌套命名空间,因此您可以使用VB中的以下代码来使用命名空间 x.y
中的类。但是,要使扩展方法起作用,完整路径必须是 Import
ed。
Imports x
Dim x As New y.SomeClass()
要检查两件事:
- 你的目标是.Net 3.5
- 您正在引用DLL 醇>
某些工具可能会错误地为不支持它们的项目建议扩展方法。
我遇到了同样的问题,可能偶然发现了解决方案。如果我用过
x.y.r.q()
,它也为我犯了同样的错误。但是如果我导入x.y,它就可以了,所以:
using x.y;
...
r.q()
很好。
所以显然你必须在声明中导入它才能使它工作。
这是很久以前我不能真正解决它,但不用说,这是用户错误。我可能重新启动了我的计算机并将其移走了。