2010-05-22 73 views
64

使用類型安全的VB.NET時,是否存在C#4'dynamic'關鍵字的等效項,即Option Strict OnVB.NET等效於C#'dynamic'與Option Strict On

+1

VB是類型安全的,無論選項嚴格打開還是關閉。閱讀關於這裏的含義http://msdn.microsoft.com/en-us/library/hbzz1a9a(VS.80).aspx – 2010-05-22 22:39:43

+0

@jdk好吧我想我必須同意。不過,我的意思是編譯時檢查類型安全性,因爲你可能已經猜到了...... – jeroenh 2010-05-23 22:56:57

+0

@jdk:人們在談論編程語言時使用的類型安全的定義是這樣的:http://en.wikipedia.org/wiki/Type_safety – 2010-07-27 01:18:39

回答

47

相當於VB.NET中的對象,但有Option Strict Off。與Option Strict On沒有相當的。換言之,dynamic關鍵字將Option Strict Off等效的功能帶給了C#。

+5

除了它不完全一樣。例如,我無法弄清楚如何在C#中動態調用方法(請參閱http://stackoverflow.com/questions/17819977/dynamic-method-calling-in-vb-without-reflection)。 – Pat 2013-07-23 20:06:04

+5

更重要的是,C#模型允許你爲特定對象制定一個例外,VB模型迫使你做得不那麼精細 – Basic 2014-07-16 21:34:07

+0

我知道這是一個老問題,但有一種方法可以做後期綁定和保持Option嚴格。從項目屬性編譯選項卡,我們可以將Late Binding設置爲「None」(並且Option Strict採用「Custom」狀態),允許在安全的環境中執行Late Binding,而不是將其設置爲Off。 – Sehnsucht 2016-07-29 14:35:53

3

您可以打開選項推斷和選項嚴格關閉,並仍然有一些非常接近。

37

VB.NET總是有內置的「動態」功能,最初稱爲後期綁定。此語法被永久支持:

Dim obj = new SomeComClass() 
obj.DoSomething() 

在.NET和COM中實現的代碼的工作,後者是最常見的用法。 C#中的動態關鍵字賦予它相同的功能。它在VB.NET版本10中確實發生了變化,但它現在也在使用DLR。它增加了對Python和Ruby等語言實現的動態綁定支持。

語法完全相同,請使用Dim關鍵字而不使用As。然而,您將不得不使用Option Strict Off,Option Infer On可以減輕這一點。它確實表明C#使用特定的關鍵字來表示動態綁定是一個非常好的舉措。 Afaik所有在VB.NET中都這麼做的請求,目前還沒有被考慮,但沒有計劃。

如果您更喜歡Option Strict On,那麼使用Partial Class關鍵字以便將某些代碼移動到另一個源文件中可能是最有效的方法。

+12

@Hans Passant:我知道,但是C#dynamic與VB的'late binding'不太一樣。在C#中,使用動態關鍵字我可以非常清楚地瞭解我的程序的動態部分。對我來說,就像告訴編譯器:「嘿,我知道我正在爲我的程序的這個特定部分做些什麼」。隨着VB.Net我必須關閉選項嚴格的整個項目,這可能會導致微妙的錯誤蔓延,因爲它。 – jeroenh 2010-05-23 23:02:05

+0

@Hans @ jeroen。在你編輯的代碼中,'app'被推斷爲'Object'類型,所以不可能*使用Excel應用程序對象'app'。例如,如果我將'app.Calculate'替換爲你有'REM等...'的地方,它就不會編譯。我認爲這是jeroen所問的問題。編譯器說'錯誤1選項Strict On不允許延遲綁定。「# – MarkJ 2010-08-31 12:13:41

+0

@MarkJ - 你是對的。我檢查了VB.NET版本10語言規範是肯定的。令人震驚的是,DLR在任何地方都沒有提及*。 Option Strict Off看起來完全不可避免。我對可憐的答案表示歉意。 – 2010-08-31 12:43:15

1

有足夠的方法來處理方法和屬性與遲綁定COM對象和類型安全(Option Strict On)。這在使用Microsoft.VisualBasic.Interaction.CallByName和System.Type.InvokeMember方法時。 (或者創建一個單獨的「部分」文件,其中Option StrictOff)。

但是,處理來自VB.NET的後期綁定事件並不像在C#中的動態類型那樣簡單。您可以在Dynamic Events in VB.NET中查看「hack」。

6

這將演示Basic對VB的描述,它與C#沒有相同的粒度。我有這一塊的C#代碼,使用反射在運行時動態調用的方法:

var listResult = tgtObj.GetType().GetMethod("GetSomeData").Invoke(tgtObj, null); 

我這樣做的原因是,「GetSomeData」可能是任何一種方法,每獲得不同的數據。在此調用的方法取決於在運行時傳遞給此對象的字符串參數,因此,「GetSomeData」的值在運行時會有所不同。

「GetSomeData」的簽名是:

public List<SomeResultSetClass> GetSomeData() 

的方法中的每一個調用的返回某種List<T>對象。接下來,我要送的listResult對象稱爲導出一個通用的方法,它看起來像這樣:

void Export<T>(List<T> exportList, string filePath, byte fileType) where T: class; 

這裏我們遇到了問題。 Invoke返回一個System.Object類型的對象。當然,List<T>也是一個System.Object,但暴露的接口是System。對象接口,而不是IList接口。如果我嘗試執行導出方法,則:

myExportObj.Export(listResult, parms.filePath, parms.fileType); 

代碼無法編譯。錯誤是:

The type arguments for method '...Export<T>...' cannot be inferred from the usage. Try specifying the type arguments explicitly.

不,謝謝!問題是編譯器找不到IList元數據,因爲它正在查看System.Object接口。現在,您可以創建一個新的List<T>,將它分配給(List<Whatever>) listResult,但這首先破壞了動態調用的目的。

的修復方法就是改變vardynamic

dynamic listResult = tgtObj.GetType().GetMethod("GetSomeData").Invoke(tgtObj, null); 

由於動態繞過靜態類型在編譯時檢查,我們沒有得到一個編譯錯誤。然後,當動態對象傳遞給Export方法時,DLR(動態語言運行時)會查看它是否可隱式轉換對象以滿足方法簽名的要求。它當然可以。

好吧,這就是C#中的事情。使用VB,線路如下所示:

Dim listResult = tgtObj.GetType().GetMethod("GetSomeData").Invoke(tgtObj, Nothing) 

使用Option Strict On,此行會按預期擾亂編譯器。關閉它,它工作正常。換句話說,在VB中,我必須關閉包含該行的整個模塊的類型檢查器。沒有比這更精細的粒度。

0

是的,ExpandoObject。

昏暗DOBJ =新System.Dynamic.ExpandoObject()

DObj.A = 「ABC」

DObj.B = 123

+1

ExpandoObject似乎在引擎蓋下使用了一個IDictionary(字符串,對象)有趣的 – Brain2000 2017-05-08 20:16:55

+0

該問題詢問如何使用Option Strict On來完成它。 'Option Strict Off' – Nick 2017-07-21 18:58:40

0

注意,即使使用選項嚴格上你仍然可以使用例如一個ExpandoObject來訪問屬性,如:

Dim doc = JsonConvert.DeserializeObject(Of ExpandoObject)("{""name"":""Bob""}") 
Dim lookup as IDictionary(Of String, Object) = doc 
lookup("name") ' Bob