Gibt es eine Entsprechung für das C # 4-Schlüsselwort 'dynamic', wenn typsicheres VB.NET verwendet wird, dh mit Option Strict On
?
Gibt es eine Entsprechung für das C # 4-Schlüsselwort 'dynamic', wenn typsicheres VB.NET verwendet wird, dh mit Option Strict On
?
Antworten:
Das Äquivalent ist Object in VB.NET, aber mit Option Strict Off
. Mit Option Strict On
gibt es kein Äquivalent. Anders ausgedrückt, das dynamische Schlüsselwort bringt esOption Strict Off
C # äquivalente Funktionen.
In VB.NET war immer die "dynamische" Funktion integriert, die ursprünglich als späte Bindung bezeichnet wurde. Diese Syntax wurde für immer unterstützt:
Dim obj = new SomeComClass()
obj.DoSomething()
Arbeitete an Code, der in .NET und COM implementiert ist, wobei letzterer die häufigste Verwendung ist. Das dynamische Schlüsselwort in C # gab ihm die gleiche Fähigkeit. Es wurde in VB.NET Version 10 geändert, verwendet jetzt jedoch auch das DLR. Dies unterstützt Sprachimplementierungen wie Python und Ruby bei der dynamischen Bindung.
Die Syntax ist genau die gleiche. Verwenden Sie das Schlüsselwort Dim ohne As. Sie müssen jedoch Option Strict Off verwenden. Option Infer On kann diesen Schlag etwas mildern. Es zeigt, dass C # mit einem bestimmten Schlüsselwort zur Signalisierung der dynamischen Bindung ein ziemlich guter Schachzug war. Afaik alle Anfragen dazu auch in VB.NET wurden bisher berücksichtigt, aber nicht geplant.
Wenn Sie Option Strict On bevorzugen, ist die Verwendung des Schlüsselworts Partial Class, mit dem Sie einen Teil des Codes in eine andere Quelldatei verschieben können, wahrscheinlich der effektivste Ansatz.
app
wird als Typ abgeleitet Object
, so ist es nicht möglich, verwenden Sie das Excel - Application - Objekt app
. Wenn ich zum Beispiel ersetze, app.Calculate
wo Sie es haben, wird REM etc...
es nicht kompiliert. Ich denke, das ist das Problem, nach dem Jeroen fragt. Der Compiler sagtError 1 Option Strict On disallows late binding.
Option
Anweisungen am Anfang der Datei überschreiben .
Dies zeigt, was Basic über VB sagt, das nicht die gleiche Granularität wie C # aufweist. Ich habe diesen Code in C #, der mithilfe der Reflektion eine Methode zur Laufzeit dynamisch aufruft:
var listResult = tgtObj.GetType().GetMethod("GetSomeData").Invoke(tgtObj, null);
Der Grund, warum ich das mache, ist, dass "GetSomeData" eine von mehreren Methoden sein kann, die jeweils unterschiedliche Daten erhalten. Welche Methode hier aufgerufen werden soll, hängt von einem Zeichenfolgenparameter ab, der zur Laufzeit an dieses Objekt übergeben wird. Daher variiert der Wert von "GetSomeData" zur Laufzeit.
Die Signatur von "GetSomeData" lautet:
public List<SomeResultSetClass> GetSomeData()
Jede der aufgerufenen Methoden gibt eine Art List<T>
Objekt zurück. Als Nächstes sende ich das listResult-Objekt an eine generische Methode namens Export, die folgendermaßen aussieht:
void Export<T>(List<T> exportList, string filePath, byte fileType) where T: class;
Hier stoßen wir auf ein Problem. Invoke gibt ein Objekt vom Typ System.Object zurück. Natürlich List<T>
ist a auch ein System.Object, aber die offenbarte Schnittstelle ist die System.Object-Schnittstelle, nicht die IList-Schnittstelle. Wenn ich versuche, die Exportmethode auszuführen, gilt Folgendes:
myExportObj.Export(listResult, parms.filePath, parms.fileType);
Der Code kann nicht kompiliert werden. Der Fehler ist:
The type arguments for method '...Export<T>...' cannot be inferred from the usage. Try specifying the type arguments explicitly.
Nein Danke!! Das Problem ist, dass der Compiler die IList-Metadaten nicht finden kann, da er die System.Object-Schnittstelle betrachtet. Jetzt können Sie eine neue erstellen List<T>
, ihr zuweisen (List<Whatever>) listResult
, aber das macht den Zweck des dynamischen Aufrufs in erster Linie zunichte.
Das Update ist zu ändern var
zu dynamic
:
dynamic listResult = tgtObj.GetType().GetMethod("GetSomeData").Invoke(tgtObj, null);
Da Dynamic die statische Typprüfung zur Kompilierungszeit umgeht, wird kein Kompilierungsfehler angezeigt. Wenn das dynamische Objekt an die Exportmethode übergeben wird, prüft das DLR (Dynamic Language Runtime), ob es das Objekt implizit umwandeln kann, um die Anforderungen der Methodensignatur zu erfüllen. Was es natürlich kann.
Ok, so funktionieren die Dinge in C #. Bei VB sieht die Linie folgendermaßen aus:
Dim listResult = tgtObj.GetType().GetMethod("GetSomeData").Invoke(tgtObj, Nothing)
Mit Option Strict On stört diese Zeile den Compiler wie erwartet. Wenn es ausgeschaltet ist, funktioniert es gut. Mit anderen Worten, in VB muss ich die Typprüfung für das gesamte Modul deaktivieren, das die Zeile enthält. Es gibt keine feinere Granularität als diese.
Sie können Option Infer On und Option Strict Off aktivieren und trotzdem etwas sehr Nahes haben.
Es gibt genügend Möglichkeiten, Methoden und Eigenschaften mit spät bindenden COM-Objekten zu verarbeiten und safe ( Option Strict On
) einzugeben . Dies bei Verwendung der Methoden Microsoft.VisualBasic.Interaction.CallByName und System.Type.InvokeMember. (Oder erstellen Sie eine separate "partielle" Datei, wo sich Option Strict
befindet Off
).
Die Behandlung von Ereignissen mit verspäteter Bindung von VB.NET ist jedoch nicht so einfach wie beim dynamischen Typ in C #. Sie können den "Hack" dafür in Dynamic Events in VB.NET überprüfen .
Das Äquivalent des dynamischen Schlüsselworts c # in Vb.Net mit der Option strict on ist als NuGet-Paket vorhanden: Dynamitey.
Nach dem Installationspaket Dynamitey kann man Vb.Net-Code wie folgt schreiben:
Option Strict On : Option Infer On : Option Explicit On
Imports Dynamitey
Module Module1
Public Sub Main()
Dim o = Nothing
o = "1234567890"
Console.WriteLine(Dynamic.InvokeMember(o, "Substring", 5)) ' writes 67890
End Sub
End Module
Oder das etwas besser lesbare:
Option Strict On : Option Infer On : Option Explicit On
Imports Dynamitey
Module Module1
<Extension()>
Public Function Substring(self As Object, offset As Integer) As String
Return CType(Dynamic.InvokeMember(self, "Substring", offset), String)
End Function
Public Sub Main()
Dim o = Nothing
o = "1234567890"
Console.WriteLine(Substring(o, 5)) ' writes 67890
End Sub
End Module
Getestet mit VS2017 und .net Framework 4.7.2.
Ja, ExpandoObject.
Dim DObj = Neues System.Dynamic.ExpandoObject ()
DObj.A = "abc"
DObj.B = 123
Option Strict On
. Ihre Antwort funktioniert nur mitOption Strict Off
Beachten Sie, dass Sie auch bei aktivierter Option Strict z. B. ein ExpandoObject verwenden können, um auf Eigenschaften wie Folgendes zuzugreifen:
Dim doc = JsonConvert.DeserializeObject(Of ExpandoObject)("{""name"":""Bob""}")
Dim lookup as IDictionary(Of String, Object) = doc
lookup("name") ' Bob