VBコードでC#拡張メソッドを呼び出す方法
-
03-07-2019 - |
質問
C#で記述されたいくつかの拡張メソッドとVBで記述された古いWebサイトを持つクラスライブラリがあります。
VBコードから拡張メソッドを呼び出したいのですが、intelisenseに表示されず、サイトにアクセスするとコンパイルエラーが発生します。
同じ名前空間に含まれる他のクラスが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」はグレー表示され、電球は、おそらく冗長なインポートを削除する機会を提供します。 (そうするとプロジェクトが壊れます。)これはVisual StudioではなくReSharperである可能性があります。
それで、長い話を短くするために、それを行うことができ、それはうまく機能するはずです。問題は、古いバージョンのVBを使用しているのか、プロジェクトが.NET 3.5を対象としていないのかとは思いませんか?
コメントに記載されているように、1つの追加の癖があります。これは、ターゲットのコンパイル時のタイプでは拡張メソッドが見つからないということです。 Object
です。
他のヒント
拡張メソッドは、静的メソッドの構文糖衣です。だから
public static string MyExtMethod(this string s)
VB.NETとC#の両方で呼び出すことができます
MyExtMethod("myArgument")
OK。エラーメッセージに基づいて、間違いなく最新の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
に注意する必要があります。VisualStudioではデフォルトでオンになっていますが、コマンドラインコンパイル、 VBCodeProvider
、および場合によってはWebサイト(デフォルトではオフweb.configで)。オフになると、VB.Netのすべてが Object
と見なされ、すべての拡張メソッドは実行時まで残されます(したがって失敗します)。
MicrosoftがVB.Netに拡張メソッドを追加したときに実際にボールを落としたと思います。C#との一貫性を保つために試した(そして失敗した)後付けだったと思います。
C#の場合と同じドット表記で呼び出すことができるかどうかはわかりませんが、静的拡張メソッドは、最初の引数を拡張型として持つ静的関数として表示されると思います。したがって、VBで実際にクラスを呼び出すことができるはずです:
StaticClass.ExtensionMethod(theString, arg1, ..., argN)
C#で記述した場所:
theString.ExtensionMethod(arg1, ..., argN);
StaticClassは、拡張メソッドを定義した静的クラスの名前です。
… VBで書かれた古いウェブサイト。
する“古い”ここでおそらくあなたもここで古いバージョンのVBを使用していることを意味しますか?とにかく、拡張メソッドは属性で装飾された単なるバニラ静的(“ Shared
”)メソッドであるため、どのような場合でも呼び出すことができるはずです 。
これが不可能な場合は、“拡張スタイル”古いバージョンのVBを使用しているか、参照しているC#アセンブリのバージョンが間違っています。
編集: x
だけでなく、 whole 名前空間、つまり xy
を Import
していることを確認してください>? VBはC#より簡単にネストされた名前空間にアクセスできるため、VBの次のコードを使用して名前空間 x.y
のクラスを使用できます。ただし、拡張メソッドが機能するには、フルパスをインポート
する必要があります。
Imports x
Dim x As New y.SomeClass()
確認する2つのこと:
- .Net 3.5をターゲットにしている
- DLLを参照しています
一部のツールは、サポートしていないプロジェクトの拡張方法を誤って提案する場合があります。
同じ問題にぶつかりましたが、偶然に解決策を見つけたかもしれません。使用した場合
x.y.r.q()
、私にも同じエラーを投げました。ただし、x.yをインポートした場合は動作したので、
using x.y;
...
r.q()
大丈夫でした。
そのため、動作させるには宣言でインポートする必要があるようです。
これはかなり前のことで、どうやって解決したらいいのかわかりませんが、言うまでもなく、ユーザーエラーでした。おそらくコンピューターを再起動して、消えてしまいました。