none
Option Strict On Late Binding RRS feed

  • Frage

  • Hallo zusammen,

    kann mir jemand sagen, wie das auszusehen hat, wenn  Option Strict On  und  Late Binding verwenden möchte

    Dim xlWorkbook As Object = Nothing
    Dim xlApp As Object = Nothing
    xlWorkbook = xlApp.Workbooks.Open(FileName)

    Oder ich habe z.B. in einem Loop
    IF row.Item(sH, DataRowVersion.Original) <> row.Item(sH, DataRowVersion.Current) Then

    Muss ich auf Option Strict On  ganz verzichten, oder gibt es da irgendeine Deklarationsmöglichkeit?

    Gruss Peter

    Donnerstag, 26. März 2015 15:02

Antworten

  • Hallo Peter,

    für jemand laut eigener Aussage "bequem ist" (O-Ton), produzierst Du einen Haufen Mist für nichts.

    Die von Dir reklamierte Unabhängigkeit ist eine Illusion. Passen die Schnittstellen wegen einer Änderung nicht, so wird es scheppern. Du hast eigentlich nur Glück, dass (zumindest bei Office) auf solche Leichtsinn Rücksicht genommen wird.

    Notwendig ist das Ganze mit .NET 4.0 nicht mehr, siehe dazu Exemplarische Vorgehensweise: Einbetten von Typinformationen aus Microsoft Office-Assemblys (C# und Visual Basic) und Du darfst Deiner Bequemlichkeit zumindest dabei fröhnen ;)

    Allerdings beim zweiten solltest Du wieder aufstehen, denn

    IF row.Item(sH, DataRowVersion.Original) <> row.Item(sH, DataRowVersion.Current) Then
    
    

    produziert zwar bei Option Strict Off keinen (Compiler-) Fehler aber trotzdem Schrott. Ein kleines Beispiel mit (D)einer falschen und mehreren "richtigeren" Lösungen:

            Dim table As New DataTable()
            table.Columns.Add("Id", GetType(Integer))
            table.Columns.Add("Name", GetType(String))
    
            Dim rows() = New DataRow() {
                table.Rows.Add(1, "ABC"),
                table.Rows.Add(2, Nothing),
                table.Rows.Add(3, "DEF"),
                table.Rows.Add(4, Nothing)}
            table.AcceptChanges()
    
            rows(0)("Name") = "abc"
            rows(1)("Name") = "ABC"
            rows(2)("Name") = Nothing
            rows(3)("Id") = DBNull.Value
            rows(3)("Name") = DBNull.Value
            For Each row As DataRow In table.Rows
                ' Nur Option Strict Off und fehlerhaft bei Nullwerten
                'If row("Name", DataRowVersion.Current) <> row("Name", DataRowVersion.Original) Then
    
                ' funktioniert wegen Überladung von Equals bei integrierten (richtig implementierten) Typen
                If Not row("Name", DataRowVersion.Current).Equals(row("Name", DataRowVersion.Original)) Then
    
                    ' DataSetExentions, konvertiert DbNull zu Nothing (Null)
                    'If row.Field(Of String)("Name", DataRowVersion.Current) <> row.Field(Of String)("Name", DataRowVersion.Original) Then
    
                    ' Für Werttypen wie Integer; Richtig in C#, Visual Basic ist leider mal wieder zu schlau
                    'If row.Field(Of Integer?)("Id", DataRowVersion.Current) <> row.Field(Of Integer?)("Id", DataRowVersion.Original) Then
                    ' nur so geht es auch in VB richtig (siehe oben)
                    'If Not row.Field(Of Integer?)("Id", DataRowVersion.Current).Equals(row.Field(Of Integer?)("Id", DataRowVersion.Original)) Then
    
                    Console.WriteLine("{0}: {1} ungleich", DirectCast(row("Id", DataRowVersion.Original), Object), row("Name"))
                Else
                    Console.WriteLine("{0}: {1} gleich", row("Id", DataRowVersion.Original), row("Name"))
                End If
            Next

    Die Geschichte mit den DataSetExtensions ist eines der Beispiele, wo die Visual Basic Erbauer am Ziel vorbei geschossen sind, und verbessern wollten, wo es nichts zu verbessern gab...

    Abschließend gesagt, liefert Option Strict Off in den wenigsten Fällen "bessere" Ergebnisse, kann (und wird) aber jede Menge Probleme verursachen. Ich habe es von Anfang an (ab VB 2002) gemieden und bin in einer anderen Sprache (C#), die es lange (vor dynamic) gar nicht konnte, ebenso gut, oft sogar besser zurecht gekommen (weil der Compiler seltener schlau sein will). Dass Visual Basic die notwendigen Anweisungen abschreckend lang gestaltet - wie DirectCast(o, Typname) -, sollte kein Grund sein, darauf zu verzichten.

    Gruß Elmar

    • Als Antwort markiert peter haus Freitag, 27. März 2015 11:32
    Donnerstag, 26. März 2015 20:05
    Beantworter

Alle Antworten

  • Hallo,
    Option Strict besagt eigentlich nur, dass alles worauf zugegriffen wird, mit 100%iger Sicherheit vorhanden sein muss.

    So sollte man beispielsweise nichts als Object deklarieren, weil man dann eben wirklich nur auf die Member von Object zugreifen kann. Dein Code sieht nach Office/Excel InterOp aus, da müsste die Deklaration in etwa so aussehen:

    Dim xlWorkbook As Excel.Workbook = Nothing
     Dim xlApp As Excel.Application = Nothing
     xlWorkbook = xlApp.Workbooks.Open(FileName)

    Ein ähnliches Problem wird auch bei deiner if-Abfrage vorliegen. row o.ä. ist als Typ einfach Object zugeordnet.

    Grundsätzlich kannst du alles mit Option Strict On machen, was auch ohne geht.


    Tom Lambert - .NET (C#) MVP
    Wozu Antworten markieren und für Beiträge abstimmen? Klicke hier.
    Nützliche Links: .NET Quellcode | C# ↔ VB.NET Konverter | Account bestätigen (Verify Your Account)
    Ich: Webseite | Code Beispiele | Facebook | Twitter | Snippets

    Donnerstag, 26. März 2015 15:20
    Moderator
  • Hallo Tom,

    >Option Strict besagt eigentlich nur, dass alles worauf zugegriffen wird, mit 100%iger Sicherheit vorhanden sein muss.
    Hast du da etwas mit Option Explicit verwechselt ??

    Ich möchte bei Excel unabhängig von der installierten Version sein.
    Deswegen möchte ich auf ein
    Imports Microsoft.Office.Interop verzichten.

    Gruss Peter

    Donnerstag, 26. März 2015 15:32
  • Hallo,
    IMHO bringt es nichts auf den Import des Namespaces zu verzichten. .NET Assemblies funktionieren nur dann, wenn sie alle nötigen Verweise finden. Die Deklaration einer Variable eines bestimmten Typs hat damit nichts zu tun.

    Tom Lambert - .NET (C#) MVP
    Wozu Antworten markieren und für Beiträge abstimmen? Klicke hier.
    Nützliche Links: .NET Quellcode | C# ↔ VB.NET Konverter | Account bestätigen (Verify Your Account)
    Ich: Webseite | Code Beispiele | Facebook | Twitter | Snippets

    Donnerstag, 26. März 2015 15:38
    Moderator
  • Hallo

    das ganze sieht am Ende so aus.
    Und ich bin unabhängig von der installierten Version.

    Am Ende der Entwicklung setze ich ComInterOp=0, es funktioniert so!

    Imports Microsoft.Office.Interop

      - - -

    #If ComInterOp = 1 Then
            Dim xlApp As Excel.Application = Nothing
            Dim xlWorkbook As Excel._Workbook = Nothing
            Dim xlWorksheet As Excel._Worksheet
            Dim exRange As Excel.Range
    #Else
            Dim xlApp As Object = Nothing
            Dim xlWorkbook As Object = Nothing
            Dim xlWorksheet As object
            Dim exRange As object
    #End If

           
            Try
    #If ComInterOp = 1 Then
                xlApp = New Excel.Application
    #Else
                xlApp=CreateObject("Excel.Application")
    #End If

                xlWorkbook = xlApp.Workbooks.Open(FileName)

    #If ComInterOp = 1 Then
                xlWorksheet = CType(xlWorkbook.Sheets.Item(1), Excel.Worksheet)
                Dim xlRange As Excel.Range = xlWorksheet.UsedRange
    #Else
                xlWorksheet =  xlWorkbook.Sheets.Item(1)
                Dim xlRange As Object
                xlRange = xlWorksheet.UsedRange
    #End If

                Dim ColMax = xlWorksheet.UsedRange.Columns.Count
                Dim MaxRows = xlWorksheet.UsedRange.Rows.Count

               - - -

    Donnerstag, 26. März 2015 15:55
  • Hallo Peter,

    für jemand laut eigener Aussage "bequem ist" (O-Ton), produzierst Du einen Haufen Mist für nichts.

    Die von Dir reklamierte Unabhängigkeit ist eine Illusion. Passen die Schnittstellen wegen einer Änderung nicht, so wird es scheppern. Du hast eigentlich nur Glück, dass (zumindest bei Office) auf solche Leichtsinn Rücksicht genommen wird.

    Notwendig ist das Ganze mit .NET 4.0 nicht mehr, siehe dazu Exemplarische Vorgehensweise: Einbetten von Typinformationen aus Microsoft Office-Assemblys (C# und Visual Basic) und Du darfst Deiner Bequemlichkeit zumindest dabei fröhnen ;)

    Allerdings beim zweiten solltest Du wieder aufstehen, denn

    IF row.Item(sH, DataRowVersion.Original) <> row.Item(sH, DataRowVersion.Current) Then
    
    

    produziert zwar bei Option Strict Off keinen (Compiler-) Fehler aber trotzdem Schrott. Ein kleines Beispiel mit (D)einer falschen und mehreren "richtigeren" Lösungen:

            Dim table As New DataTable()
            table.Columns.Add("Id", GetType(Integer))
            table.Columns.Add("Name", GetType(String))
    
            Dim rows() = New DataRow() {
                table.Rows.Add(1, "ABC"),
                table.Rows.Add(2, Nothing),
                table.Rows.Add(3, "DEF"),
                table.Rows.Add(4, Nothing)}
            table.AcceptChanges()
    
            rows(0)("Name") = "abc"
            rows(1)("Name") = "ABC"
            rows(2)("Name") = Nothing
            rows(3)("Id") = DBNull.Value
            rows(3)("Name") = DBNull.Value
            For Each row As DataRow In table.Rows
                ' Nur Option Strict Off und fehlerhaft bei Nullwerten
                'If row("Name", DataRowVersion.Current) <> row("Name", DataRowVersion.Original) Then
    
                ' funktioniert wegen Überladung von Equals bei integrierten (richtig implementierten) Typen
                If Not row("Name", DataRowVersion.Current).Equals(row("Name", DataRowVersion.Original)) Then
    
                    ' DataSetExentions, konvertiert DbNull zu Nothing (Null)
                    'If row.Field(Of String)("Name", DataRowVersion.Current) <> row.Field(Of String)("Name", DataRowVersion.Original) Then
    
                    ' Für Werttypen wie Integer; Richtig in C#, Visual Basic ist leider mal wieder zu schlau
                    'If row.Field(Of Integer?)("Id", DataRowVersion.Current) <> row.Field(Of Integer?)("Id", DataRowVersion.Original) Then
                    ' nur so geht es auch in VB richtig (siehe oben)
                    'If Not row.Field(Of Integer?)("Id", DataRowVersion.Current).Equals(row.Field(Of Integer?)("Id", DataRowVersion.Original)) Then
    
                    Console.WriteLine("{0}: {1} ungleich", DirectCast(row("Id", DataRowVersion.Original), Object), row("Name"))
                Else
                    Console.WriteLine("{0}: {1} gleich", row("Id", DataRowVersion.Original), row("Name"))
                End If
            Next

    Die Geschichte mit den DataSetExtensions ist eines der Beispiele, wo die Visual Basic Erbauer am Ziel vorbei geschossen sind, und verbessern wollten, wo es nichts zu verbessern gab...

    Abschließend gesagt, liefert Option Strict Off in den wenigsten Fällen "bessere" Ergebnisse, kann (und wird) aber jede Menge Probleme verursachen. Ich habe es von Anfang an (ab VB 2002) gemieden und bin in einer anderen Sprache (C#), die es lange (vor dynamic) gar nicht konnte, ebenso gut, oft sogar besser zurecht gekommen (weil der Compiler seltener schlau sein will). Dass Visual Basic die notwendigen Anweisungen abschreckend lang gestaltet - wie DirectCast(o, Typname) -, sollte kein Grund sein, darauf zu verzichten.

    Gruß Elmar

    • Als Antwort markiert peter haus Freitag, 27. März 2015 11:32
    Donnerstag, 26. März 2015 20:05
    Beantworter
  • Hallo Elmar,

    vielen Dank für dein aufschlussreiches Beispiel, ich habe es mal durchgespielt.

    Herzliche Grüsse

    Peter

    Freitag, 27. März 2015 11:32