簡體   English   中英

為什么VB.Net在接口上找不到擴展方法?

[英]Why can't VB.Net find an extension method on an interface?

我有一個具有擴展方法的C#庫,類似於:

public interface ISomething { ... }
public class SomethingA : ISomething { ... }
public class SomethingB : ISomething { ... }

public static class SomethingExtensions 
{
    public static int ExtensionMethod(this ISomething input, string extra) 
    {
    }
}

如果從C#調用該擴展程序,則工作正常,但如果從外部VB.Net應用程序調用,則存在問題:

Dim something = Me.SomethingManager.GetSomething(key)
Dim result = something.ExtensionMethod("extra")

這樣可以編譯良好,但是在運行時引發異常:

找不到類型為“ SomethingB”的公共成員“ ExtensionMethod”。

如果將VB.Net更改為顯式地使其成為接口,那么它將起作用:

Dim something as ISomething = Me.SomethingManager.GetSomething(key)
Dim result = something.ExtensionMethod("extra")

為什么? 為什么擴展方法在接口上起作用,但不能在實現該接口的類上起作用? 如果使用子類,是否會有同樣的問題? VB.Net擴展方法的實現是否不完整?

我可以在C#庫中做任何事情來使VB.Net在沒有顯式接口的情況下工作嗎?

關閉選項推斷后,此代碼...

Dim something = Me.SomethingManager.GetSomething(key)
Dim result = something.ExtensionMethod("extra")

...是相同的...

Dim something As Object = Me.SomethingManager.GetSomething(key)
Dim result As Object = something.ExtensionMethod("extra")

由於something屬於Object類型,因此找不到擴展方法,因為它未在Object類型上定義。

現在,如果將Option Infer On設置為,則將獲得與C#的var關鍵字相同的結果。 類型將被自動推斷。 請注意,這也可能破壞現有代碼,但是可以為特定文件啟用該代碼,例如Option Strict

最佳實踐是將“ Option Strict Option Infer和“ Option Infer都設置為“開”。

如果它拋出異常而不是給出編譯時錯誤,則表明您已禁用Option Strict ...我不知道那種情況下擴展方法會發生什么,因為它們通常是在編譯時解決的,但是關閉Option Strict后,綁定將繼續進行。

我建議您打開Option Strict,一切都應該很好。

(根據Richard的回答,您需要導入名稱空間,但我假設您已經完成了該操作。如果您在嚴格啟用選項后忘記這樣做,則會看到編譯時錯誤。 )

為喬恩(Jon)指出正確的方向而歡呼,但是這里有足夠的需要一個完整的答案。

擴展方法是一個編譯器技巧,因此(在C#中):

var something = this.SomethingManager.GetSomething(key);
var result = something.ExtensionMethod("extra");

在編譯時轉換為:

ISomething something = this.SomethingManager.GetSomething(key);
int result = SomethingExtensions.ExtensionMethod(something, "extra");

作為類方法出現的靜態擴展方法僅僅是編譯器的靈巧性。

問題在於,VB中的Dim與C#中的var 感謝VB的后期綁定,它更接近dynamic

因此,使用VB中的原始示例:

Dim something = Me.SomethingManager.GetSomething(key)
Dim result = something.ExtensionMethod("extra")

與C#不同,在VB中,要弄清楚something類型直到運行時,並且不會使擴展方法起作用的編譯器聰明。 如果明確聲明了類型,則可以解析擴展方法,但是如果綁定得晚,則擴展方法將永遠無法工作。

如果他們使用Option Strict On (如Jon所建議的那樣),那么它們將被迫始終聲明類型,發生早期綁定,並且編譯器的聰明才智使擴展方法起作用。 無論如何,這都是最佳實踐,但是由於他們沒有這樣做,這對他們來說是一個痛苦的改變。

這個故事的寓意:如果您希望VB的任何人靠近它,請不要在您的API中使用擴展方法:-S

您是否導入了包含定義該名稱空間的類的名稱空間。

例如。 如果沒有,您將看不到任何LINQ to Objects擴展方法

Imports System.Linq

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM