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

时间:2008-10-17 17:25:33

标签: c# vb.net extension-methods class-library

我有一个类库,其中包含一些用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.

10 个答案:

答案 0 :(得分:8)

它适用于我,虽然有一些怪癖。首先,我创建了一个面向.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?

如评论中所述:还有一个额外的怪癖,即extension methods won't be found when the compile-time type of the target is Object

答案 1 :(得分:2)

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

public static string MyExtMethod(this string s)

可以在VB.NET和C#中用

调用
MyExtMethod("myArgument")

答案 2 :(得分:2)

行。基于错误消息,您肯定使用最新的VB版本(VB 9!)或者该错误与此问题无关,因为如果方法你会得到另一个错误没找到:

  

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

答案 3 :(得分:1)

Imports x.y

'...'
Dim r As String = "greg"
Dim s As String = r.q() 'same as z.q(r) 

答案 4 :(得分:1)

我想我encountered a similar problem: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的方法 - 编译器无法用对{的静态调用替换扩展方法的语法糖{1}}。

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

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

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

答案 5 :(得分:0)

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

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

在C#中你刚才写的:

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

使用StaticClass作为定义扩展方法的静态类的名称。

答案 6 :(得分:0)

  

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

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

如果无法做到这一点,您可以尝试在旧版本的VB中将它们称为“扩展样式”,或者引用错误版本的C#程序集。

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

Imports x
Dim x As New y.SomeClass()

答案 7 :(得分:0)

要检查两件事:

  1. 你的目标是.Net 3.5
  2. 您正在引用DLL
  3. 某些工具可能会错误地为不支持它们的项目建议扩展方法。

答案 8 :(得分:0)

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

x.y.r.q()

,它也为我犯了同样的错误。但是如果我导入x.y,它就可以了,所以:

using x.y;
...
r.q()

很好。

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

答案 9 :(得分:-1)

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