简体   繁体   English

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

[英]How can I call C# extension methods in VB code

I have a class library with some extension methods written in C# and an old website written in VB. 我有一个类库,其中包含一些用C#编写的扩展方法和一个用VB编写的旧网站。

I want to call my extension methods from the VB code but they don't appear in intelisense and I get compile errors when I visit the site. 我想从VB代码调用我的扩展方法,但它们没有出现在intelisense中,当我访问该站点时出现编译错误。

I have got all the required Import s because other classes contained in the same namespaces are appearing fine in Intelisense. 我已经获得了所有必需的Import,因为同一名称空间中包含的其他类在Intelisense中看起来很好。

Any suggestions 有什么建议

EDIT: More info to help with some comments. 编辑:更多信息,以帮助一些评论。

my implementation looks like this 我的实现看起来像这样

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

    }
}

and my usage like this 和我这样的用法

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.

It works for me, although there are a couple of quirks. 它对我有用,虽然有一些怪癖。 First, I created a C# class library targeting .NET 3.5. 首先,我创建了一个面向.NET 3.5的C#类库。 Here's the only code in the project: 这是项目中唯一的代码:

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);
    }
  }
}

Then I created a VB console app targeting .NET 3.5, and added a reference to my C# project. 然后我创建了一个面向.NET 3.5的VB控制台应用程序,并添加了对我的C#项目的引用。 I renamed Module1.vb to Test.vb, and here's the code: 我将Module1.vb重命名为Test.vb,这里是代码:

Imports ExtensionLibrary

Module Test

    Sub Main()
        Console.WriteLine("Hello".CustomExtension())
    End Sub

End Module

This compiles and runs. 这编译并运行。 (I would have called the method Reverse() but I wasn't sure whether VB might magically have reverse abilities already somewhere - I'm not a VB expert by a long chalk.) (我本来会调用方法Reverse()但是我不确定VB是否可能已经在某处神奇地具有反向能力 - 我不是一个长期粉笔的VB专家。)

Initially, I wasn't offered ExtensionLibrary as an import from Intellisense. 最初,我没有提供ExtensionLibrary作为Intellisense的导入。 Even after building, the "Imports ExtensionLibrary" is greyed out, and a lightbulb offers the opportunity to remove the supposedly redundant import. 即使在构建之后,“Imports ExtensionLibrary”也会变灰,并且灯泡提供了删除所谓冗余导入的机会。 (Doing so breaks the project.) It's possible that this is ReSharper rather than Visual Studio, mind you. (这样做会破坏项目。)请注意,这可能是ReSharper而不是Visual Studio。

So to cut a long story short, it can be done, and it should work just fine. 所以简而言之,可以做到,它应该可以正常工作。 I don't suppose the problem is that you're either using an old version of VB or your project isn't targeting .NET 3.5? 我不认为问题是您要么使用旧版本的VB,要么您的项目不是针对.NET 3.5?

As noted in comments: there's one additional quirk, which is that extension methods won't be found when the compile-time type of the target is Object . 如注释中所述:还有一个额外的怪癖,即当目标的编译时类型为Object时,将找不到扩展方法

Extension methods are just syntactic sugar for static methods. 扩展方法只是静态方法的语法糖。 So 所以

public static string MyExtMethod(this string s)

can be called in both VB.NET and C# with 可以在VB.NET和C#中调用

MyExtMethod("myArgument")

OK. 好。 Based on the error message you are definitely not using the most recent VB version (VB 9!) or the error isn't related to this problem at all because then you'd get another error if the method wasn't found: 根据错误消息,您肯定没有使用最新的VB版本(VB 9!)或错误与此问题无关,因为如果找不到该方法,您将收到另一个错误:

Error 1 'q' is not a member of 'String'. 错误1'q'不是'String'的成员。

I think I've encountered a similar problem : VB.Net is quite happy to compile on through extension methods and leave them to be inferred at run-time if Option Strict is off. 我想我遇到了类似的问题 :VB.Net非常乐意通过扩展方法进行编译,如果Option Strict关闭,可以在运行时进行推断。

However, VB.Net really doesn't seem to like extension methods on basic types. 但是,VB.Net似乎并不喜欢基本类型的扩展方法。 You can't extend Object and it can't resolve it if you do: 如果您执行以下操作,则无法扩展Object并且无法解析它:

C# 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");

However this goes wrong in VB.Net: 但是这在VB.Net中出错了:

Option Infer On
Option Explicit On
Option Strict Off
Imports NS
...

    Dim r as String = "test" 
    r.Something()

That compiles without error, but at run time fails because Something is not a method of String - the compiler has failed to replace the syntactic sugar of the extension method with the the static call to Utility.Something . 编译没有错误,但在运行时失败,因为Something不是String的方法 - 编译器无法用对Utility.Something的静态调用替换扩展方法的语法糖。

The question is why? 问题是为什么? Well unlike C#, VB.Net can't handle any extension to Object ! 与C#不同, VB.Net无法处理Object任何扩展 The valid extension method in C# confuses the VB.Net compiler. C#中的有效扩展方法会混淆VB.Net编译器。

As a general VB.Net rule, I'd avoid using extension methods with any of the basic .Net types ( Object , String , Integer , etc). 作为一般的VB.Net规则,我避免使用任何基本.Net类型( ObjectStringInteger等)的扩展方法。 You also have to be careful with Option Infer as while it's on by default in Visual Studio it's off by default for command line compiles, VBCodeProvider , and possibly in web sites (depending on your web.config). 您还必须小心使用Option Infer VBCodeProvider ,因为默认情况下它在Visual Studio中处于打开状态,默认情况下,命令行编译, VBCodeProvider以及可能在网站中(取决于您的web.config)。 When it's off everything in VB.Net is considered to be an Object and all extension methods will be left until run time (and will therefore fail). 当它关闭时,VB.Net中的所有内容都被认为是一个Object ,所有扩展方法都将保留到运行时(因此会失败)。

I think Microsoft really dropped the ball when they added extension methods to VB.Net, I think it was an afterthought to try (and fail) to make it consistent with C#. 我认为微软在向VB.Net添加扩展方法时真的放弃了它,我认为这是尝试(并且失败)使其与C#保持一致的事后想法。

Imports x.y

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

I don't know if you can call them in the same dot notation as you would in C#, but I would think that the static extension methods would show up as static functions with the fist argument as the extended type. 我不知道你是否可以用与C#中相同的点符号来调用它们,但我认为静态扩展方法将显示为静态函数,其中第一个参数为扩展类型。 So you should be able to call the actually class in VB with: 所以你应该能够用VB调用实际的类:

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

Where in C# you would have just written: 在C#中,您刚刚写完:

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

With StaticClass being the name of the static class in which you defined your extension methods. StaticClass是您在其中定义扩展方法的静态类的名称。

… and an old website written in VB. ......还有一个用VB编写的旧网站。

Does “old” here imply perhaps that you also use an old version of VB here? 这里的“旧”是否意味着你也可以在这里使用旧版本的VB? Anyway, since extension methods are just vanilla static (“ Shared ”) methods decorated with an attribute, you should be able to call them in any case. 无论如何,因为扩展方法只是用属性修饰的vanilla static(“ Shared ”)方法,所以你应该能够在任何情况下调用它们。

If this isn't possible you either try to call them “extension style” in an old version of VB or you're referencing the wrong version of your C# assembly. 如果这不可能,您可以尝试在旧版本的VB中将它们称为“扩展样式”,或者引用错误版本的C#程序集。

Edit: are you sure you're Import ing the whole namespace, ie xy and not just x ? 编辑:你确定要Import 整个命名空间,即xy而不只是x吗? VB is able to access nested namespaces easier than C# so you can use classes from namespace xy using the following code in VB. VB能够比C#更容易地访问嵌套命名空间,因此您可以使用VB中的以下代码来使用命名空间xy中的类。 However, for extension methods to work, the full path has to be Import ed. 但是,要使扩展方法起作用,必须Import 完整路径。

Imports x
Dim x As New y.SomeClass()

Two things to check: 要检查两件事:

  1. You're Targeting .Net 3.5 你是针对.Net 3.5
  2. You're referencing the DLL 您正在引用DLL

Some tools might incorrectly suggest extension methods for projects that don't support them. 某些工具可能会错误地为不支持它们的项目建议扩展方法。

I ran into the same problem, and might accidentally have stumbled upon the solution. 我遇到了同样的问题,可能偶然发现了解决方案。 If I used 如果我用过

x.y.r.q()

, it threw the same error for me as well. ,它也给我带来了同样的错误。 But if I imported xy, it worked, so: 但是,如果我导入xy,它可以工作,所以:

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

was fine. 很好。

So apparently you have to import it in the declaration to make it work. 所以显然你必须在声明中导入它才能使它工作。

This was quite a while ago and I can't really how I solved it, but needless to say, it was user error. 这是很久以前我不能真正解决它,但不用说,这是用户错误。 I probably restarted my computer and away it went. 我可能重新启动了我的计算机然后就把它拿走了。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM