10

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

10 回答 10

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?

如评论中所述:还有一个额外的怪癖,即当目标的编译时类型为Object.

于 2008-10-17T19:03:28.267 回答
2

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

public static string MyExtMethod(this string s)

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

MyExtMethod("myArgument")
于 2008-10-17T17:30:38.733 回答
2

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

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

于 2008-10-17T18:46:19.453 回答
1
Imports x.y

'...'
Dim r As String = "greg"
Dim s As String = r.q() 'same as z.q(r) 
于 2008-10-17T18:40:25.240 回答
1

我想我遇到过类似的问题: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因为它在 Visual Studio 中默认打开,在命令行编译时默认关闭VBCodeProvider,并且可能在网站中(取决于您的 web.config)。当它关闭时,VB.Net 中的所有内容都被认为是一个Object,并且所有扩展方法都将保留到运行时(因此会失败)。

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

于 2012-08-31T08:08:38.663 回答
0

我不知道您是否可以像在 C# 中那样以点表示法调用它们,但我认为静态扩展方法将显示为静态函数,第一个参数作为扩展类型。所以你应该能够在 VB 中调用实际的类:

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

您刚刚在 C# 中的哪个位置编写:

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

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

于 2008-10-17T17:31:37.030 回答
0

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

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

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

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

Imports x
Dim x As New y.SomeClass()
于 2008-10-17T18:33:14.847 回答
0

要检查的两件事:

  1. 您的目标是 .Net 3.5
  2. 您正在引用 DLL

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

于 2008-10-17T19:21:19.383 回答
0

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

x.y.r.q()

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

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

很好。

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

于 2010-09-18T14:39:05.110 回答
-1

这是很久以前的事了,我真的不知道如何解决它,但不用说,这是用户错误。我可能重新启动了我的计算机,然后它就消失了。

于 2009-02-07T15:42:13.793 回答