Angepinnt Böses aus VB6/VB2003 – und die richtigen VB.NET-Alternativen

    • VB.NET

    Es gibt 15 Antworten in diesem Thema. Der letzte Beitrag () ist von SeriTools.

      Böses aus VB6/VB2003 – und die richtigen VB.NET-Alternativen

      Da es immer wieder Umsteiger von VB6 oder Leute, die versuchen, ein VB6-Buch auf VB.NET anzuwenden, gibt, fasse ich hier mal die bösen, veralteten VB6-Funktionen zusammen, die es noch in VB.NET gibt, samt ihrer korrekten Alternativen.

      Warum sollte man die VB6-Funktionen nicht weiterverwenden?
      Sie sind veraltet. Sie verhalten sich anders. Sie sind nicht standardkonform in der .NET-Umgebung (sie sind standardkonform zu VB6) und lassen sich daher nicht einfach in C# konvertieren. Sie führen zu Code, welcher grundlegende Gesetze der objektorientierten Programmierung verletzt.

      Leider basieren viele Tutorials, Snippets und Forenbeiträge immer noch auf diesen veralteten Funktionen und auch der automatische Import des Microsoft.VisualBasic-Namespaces (in welchem diese ganzen Funktionen liegen) macht es dem Anfänger schwierig zu erkennen, dass man diese Funktionen nicht verwenden sollte. Ein "Veraltet"-Hinweis ("deprecated") im IntelliSense wäre wünschenswert.

      By the way: Einige VB6-Funktionen (vor allem mathematische) wurden aus VB.NET schon durch deren Pendants Math.Funktion() ersetzt.

      Die "bösen" Funktionen:
      Sortiert nach Kategorien (vielen Dank an ErfinderDesRades):
      Spoiler anzeigen
      • keine böse Funktion
        (Ehe ich zB. eine Methode selber schreibe, nehme ich lieber Funktionen aus dem VisualBasic-Namespace.)
        1. AscW() - .NET: bei konstantem Parameter: AscW(), ansonsten: System.Convert.ToInt16()
        2. AppActivate() - .NET: Leider keine einfache Alternative, da AppActivate() wohl direkt auf die WINAPI zugreift.
        3. InputBox() - .NET: Eigenen Dialog verwenden, viel mehr Möglichkeiten
        4. StrReverse() - .NET: selber schreiben (wenn man denn sowas eigenartiges je braucht).
        5. MsgBox() - .NET: System.Windows.Forms.MessageBox.Show() IMO: egal ob MessageBox oder MsgBox: schlecht von der Experience her. Also setzt man es ein, wo es selten gebraucht wird, und der Aufwand eines ordentlichen Dialoges auf später vertagt werden kann.
        6. CreateObject("Com.Object.Name") - .NET: System.Activator.CreateInstance(System.Type.GetTypeFromProgID("Com.Object.Name"))
        7. GetObject() - .NET: z.B.: codeproject.com/KB/cs/CSGetObject.aspx

      • Auflistungen
        1. IsArray() - .NET: Typvergleich ausführen
        2. LBound() - .NET: Array.GetLowerBound()
        3. UBound() - .NET: Array.GetUpperBound()
        4. ReDim - .NET: Verwendung von AuflistungsKlassen, wie List(Of T)
        5. ArrayList - .NET: List(Of T)
        6. Collection (VB6) - .NET: List(Of T) oder Dictionary(Of TKey, TValue)
        7. HashTable (VB2003) - UNTYPISIERT! .NET: Dictionary(Of TKey, TValue)

      • Reflection
        1. CallByName() - .NET: Late Binding ist schlecht! Es würde über System.Refelection gehen.
        2. SystemTypeName() - .NET: unnötig
        3. TypeName() - .NET: .GetType.Name/FullName()
        4. VarType(), VbTypeName() - .NET: unnötig.

      • File-Handling
        1. ChDir() bzw. ChDrive() - .NET: System.IO.Directory.SetCurrentDirectory() bzw. Eigenschaft System.Environment.CurrentDirectory() setzen
        2. CurDir() - .NET: System.IO.Directory.GetCurrentDirectory() bzw. Eigenschaft System.Environment.CurrentDirectory() auslesen
        3. Dir() - .NET: System.IO.GetDirectoryInfo() und die dazugehörigen Klassen verwenden.
        4. File*(), FileSystemObject, EOF(), FreeFile(), Input(), Loc(), Lock() etc., also Dateizugriff in VB6 - .NET: System.IO-Namespace benutzen
        5. Kill() - .NET: System.IO.File.Delete()
        6. MkDir() - .NET: System.IO.Directory.CreateDirectory()
        7. Rename() - .NET: System.IO.File/Directory.Move()
        8. RmDir() - .NET: System.IO.Directory.Delete()
        9. & und annere String-Operationen mit Dateipfaden - .NET: System.IO.Path.Combine und annere Path-Methoden nutzen

      • Fehlerbehandlung
        1. On Error GoTo ... - .NET: TryCatch - Konzept verwenden
        2. ErrorToString() - .NET: TryCatch - Konzept verwenden
        3. GetException() - .NET: TryCatch - Konzept verwenden

      • Strings
        1. Asc() - .NET: bei konstantem Parameter: AscW(), ansonsten: System.Convert.ToInt16() für UTF-8, bei anderen Encodings msdn.microsoft.com/en-us/library/5881c0k9.aspx
        2. Chr() - .NET: bei konstantem Parameter: ChrW(), ansonsten: System.Convert.ToChar() für UTF-8, bei anderen Encodings msdn.microsoft.com/en-us/library/khac988h.aspx
        3. CBool(), CByte(), CChar(), CDate(), CDbl(), CDec(), CInt(), CLng(), CObj(), CSByte(), CShort(), CSng(), CStr(), CUInt(), CULng(), CUShort() - diese Schlüsselworte sind i.a. sehr performant - bei Konstanten werden sie zT. schon vom Compiler ausgewertet und nehmen zur Laufzeit keine Rechenzeit in Anspruch.
          sie sind aber nicht dazu konzipiert, um von String zu konvertieren - dafür sind die Parse-Functions des ZielTypen vorgesehen (DateTime.Parse(), Boolean.Parse(), ...).
        4. Format(), Format* - .NET: System.String.Format()
        5. GetChar() - .NET: deinString(index) bzw. deinString.Char(index)
        6. InStr() - .NET: String.Contains() bzw. String.IndexOf()
        7. InStrRev() - .NET: String.LastIndexOf()
        8. IsDBNull() - .NET: DataRow.IsNull(), DataReader.IsDbNull(), Convert.IsDbNull()
        9. IsNumeric(), IsDate() etc. - .NET: Integer/Double/Date/.TryParse()
        10. Join() - .NET: String.Join() oder string &= "...", bei vielen Verkettungen ist ein StringBuilder empfehlenswert.
        11. LCase() - .NET: String.ToLower()
        12. Left(), Right(), Mid() - .NET: String.Substring()
        13. Len() - .NET: String.Length()
        14. LTrim() - .NET: String.TrimStart(Nothing)
        15. LSet(), RSet(), Space() - .NET: String.PadLeft()/PadRight()
        16. Oct(), Hex() - .NET: Convert.ToString(value,8) (oktal), Convert.ToString(value,16) (hexadezimal), s.a. Convert.ToString(value,2) (binär)
        17. Replace() - .NET: String.Replace()
        18. Split() - .NET: String.Split()
        19. Str() - .NET: .ToString()
        20. StrComp() - .NET: String.Compare() / String.CompareTo()
        21. StrConv(conv) - .NET: im nicht-asiatischen Sprachraum unnötig - einzig mit VbStrConv.ProperCase als Parameter manchmal sinnvoll
        22. StrDup() - .NET: String.Pad-Left/-Right, oder zB: New String(" "c, 20) erzeugt einen String mit 20 Spaces.
        23. UCase() - .NET: String.ToUpper()
        24. Val() - .NET: explizite Typkonvertierung durchführen (z.B. .ToString())

      • Sonstige: die Aufzählung versucht nach Wichtigkeit geordnet zu sein
        1. Date...(), Day(), Hour() etc. - .NET: Die Klassen System.DateTime und System.TimeSpan bieten alle Funktionalität, die man sich zur Behandlung von Zeit-Werten nur wünschen kann - Zeiten-Handling ist im Grunde ein ähnlich komplexer Bereich wie das String-Handling
        2. Or / And - .NET: OrElse / AndAlso
        3. IIf() - .NET: If(expression, TruePart, FalsePart) oder If(expression, FalsePart)
        4. Shell() - .NET: System.Diagnostics.Process.Start()
        5. Command() - .NET: System.Environment.CommandLine()
        6. Environ() - .NET: System.Environment.GetEnvironmentVariable()
        7. *Setting(), GetAllSettings() - .NET: Microsoft.Win32.Registry/RegistryKey benutzen
        8. Randomize(), Rnd() - .NET: System.Random benutzen.
        9. Choose(index, variable) - .NET: variable(index) oder (bei manchen Listen o.ä.) variable.Item(index)
        10. Beep() - .NET: Keine äquivaltente Methode (benutzt WINAPI), außer für Konsolenfenster: System.Console.Beep() - Achtung: Funktioniert nicht auf XP x64/Vista x64, wurde in Windows 7 gelöst.
        11. DDB() - .NET: Folgende Formel anstatt Parameter benutzen: Depreciation / Period = ((Cost – Salvage) * Factor) / Life
        12. Filter() - .NET: Keine direkte Entsprechung
        13. Fix(), Int() - .NET: System.Math.Truncate()
        14. FV() - .NET: selber berechnen.
        15. Hex() - .NET: Convert.ToString(value,16)
        16. IPmt() - .NET: selber berechnen.
        17. IRR() - .NET: selber berechnen.
        18. IsNothing() - .NET: If variable Is Nothing Then [...]
        19. MIRR() - .NET: selber berechnen.
        20. NPer() - .NET: selber berechnen.
        21. NPV() - .NET: selber berechnen.
        22. Pmt(), PPmt(), PV() - .NET: selber berechnen.
        23. QBColor() - .NET: unnötig.
        24. Rate() - .NET: selber berechnen.
        25. RGB() - .NET: Color-Klasse benutzen.
        26. SLN() - .NET: selber berechnen.
        27. Switch() - .NET: Switch benutzen bzw. While oder For
        28. SYD() - .NET: selber berechnen.


      Alphabetisch sortiert:
      Spoiler anzeigen

      • AppActivate() - .NET: Leider keine einfache Alternative, da AppActivate() wohl direkt auf die WINAPI zugreift.
      • Asc() - .NET: Keine direkte Entsprechung, da Asc() nur ASCII-Werte verarbeiten kann und VB.NET vollkommen auf Unicode basiert. Möglicherweise mit System.Convert.ToByte()
      • AscW() - .NET: bei konstantem Parameter: AscW(), ansonsten: System.Convert.ToInt16()
      • Beep() - .NET: Keine äquivaltente Methode (benutzt WINAPI), außer für Konsolenfenster: System.Console.Beep() - Achtung: Funktioniert nicht auf XP x64/Vista x64, wurde in Windows 7 gelöst.
      • CallByName() - .NET: Late Binding ist schlecht! Es würde über System.Refelection gehen.
      • CBool(), CByte(), CChar(), CDate(), CDbl(), CDec(), CInt(), CLng(), CObj(), CSByte(), CShort(), CSng(), CStr(), CUInt(), CULng(), CUShort() - .NET: bei konstantem Parameter: CBool() etc. weiterbenutzen; bei variablem Parameter: System.Convert.ToDatentyp() / variable.ToString(), wobei Datentyp für den .NET-Datentyp steht, nicht für eine Abkürzung wie in CLng für Long.
      • ChDir() bzw. ChDrive() - .NET: System.IO.Directory.SetCurrentDirectory() bzw. Eigenschaft System.Environment.CurrentDirectory() setzen
      • Choose(index, variable) - .NET: variable(index) oder (bei manchen Listen o.ä.) variable.Item(index)
      • Chr() - .NET: Keine direkte Entsprechung, siehe Asc()
      • ChrW() - .NET: bei konstantem Parameter: ChrW(); ansonsten: System.Convert.ToChar()
      • Command() - .NET: System.Environment.CommandLine()
      • CreateObject("Com.Object.Name") - .NET: System.Activator.CreateInstance(System.Type.GetTypeFromProgID("Com.Object.Name"))
      • CurDir() - .NET: System.IO.Directory.GetCurrentDirectory() bzw. Eigenschaft System.Environment.CurrentDirectory() auslesen
      • Date...(), Day(), Hour() etc. - .NET: Die Klasse System.DateTime bietet entsprechende Funktionen an. In manchen Fällen kann man auch System.TimeSpan benutzen
      • DDB() - .NET: Folgende Formel anstatt Parameter benutzen: Depreciation / Period = ((Cost – Salvage) * Factor) / Life
      • *Setting(), GetAllSettings() - .NET: Microsoft.Win32.Registry/RegistryKey benutzen
      • Dir() - .NET: System.IO.GetDirectoryInfo() und die dazugehörigen Klassen verwenden.
      • Environ() - .NET: System.Environment.GetEnvironmentVariable()
      • File*(), FileSystemObject, EOF(), FreeFile(), Input(), Loc(), Lock() etc., also Dateizugriff in VB6 - .NET: System.IO-Namespace benutzen
      • ErrorToString() - .NET: Evtl. System.Exception benutzen
      • Filter() - .NET: Keine direkte Entsprechung
      • Fix(), Int() - .NET: System.Math.Truncate()
      • Format(), Format* - .NET: System.String.Format()
      • FV() - .NET: selber berechnen.
      • GetChar() - .NET: deinString(index) bzw. deinString.Char(index)
      • GetException() - .NET: unnötig.
      • GetObject() - .NET: z.B.: codeproject.com/KB/cs/CSGetObject.aspx
      • HashTable (VB2003) - UNTYPISIERT! .NET: Dictionary(Of TKey, TValue)
      • Hex() - .NET: Convert.ToString(value,16)
      • IIf() - .NET: If(expression, TruePart, FalsePart) oder If(expression, FalePart)
      • InputBox() - .NET: Eigenen Dialog verwenden, viel mehr Möglichkeiten
      • InStr() - .NET: String.Contains() bzw. String.IndexOf()
      • InStrRev() - .NET: String.LastIndexOf()
      • IPmt() - .NET: selber berechnen.
      • IRR() - .NET: selber berechnen.
      • IsArray() - .NET: Typvergleich ausführen
      • IsDBNull() - .NET: DataRow.IsNull(), DataReader.IsDbNull(), Convert.IsDbNull()
      • IsNothing() - .NET: If variable Is Nothing Then [...]
      • IsNumeric(), IsDate() etc. - .NET: Integer/Double/Date/.TryParse()
      • Join() - .NET: String.Join() oder string &= "...", bei vielen Verkettungen ist ein StringBuilder empfehlenswert.
      • Kill() - .NET: System.IO.File.Delete()
      • LBound() - .NET: Array.GetLowerBound()
      • LCase() - .NET: String.ToLower()
      • Left(), Right(), Mid() - .NET: String.Substring()
      • Len() - .NET: String.Length()
      • LSet(), RSet(), Space() - .NET: String.PadLeft()/PadRight()
      • LTrim() - .NET: String.TrimStart(Nothing)
      • MIRR() - .NET: selber berechnen.
      • MkDir() - .NET: System.IO.Directory.CreateDirectory()
      • MsgBox() - .NET: System.Windows.Forms.MessageBox.Show() IMO: egal ob MessageBox oder MsgBox: schlecht von der Experience her. Also setzt man es ein, wo es selten gebraucht wird, und der Aufwand eines ordentlichen Dialoges auf später vertagt werden kann.
      • NPer() - .NET: selber berechnen.
      • NPV() - .NET: selber berechnen.
      • Oct() - .NET: Convert.ToString(value,8)
      • Pmt(), PPmt(), PV() - .NET: selber berechnen.
      • QBColor() - .NET: unnötig.
      • Randomize(), Rnd() - .NET: System.Random benutzen.
      • Rate() - .NET: selber berechnen.
      • ReDim() - .NET: Entweder Array.Resize, wenn es unbedingt sein muss; VIEL besser ist eine List(Of T) anstatt eines Arrays zu benutzen
      • Rename() - .NET: System.IO.File/Directory.Move()
      • Replace() - .NET: String.Replace()
      • RGB() - .NET: Color-Klasse benutzen.
      • RmDir() - .NET: System.IO.Directory.Delete()
      • Shell() - .NET: System.Diagnostics.Process.Start()
      • SLN() - .NET: selber berechnen.
      • Split() - .NET: String.Split()
      • Str() - .NET: .ToString()
      • StrComp() - .NET: kleine If-Abfrage selber schreiben.
      • StrConv(), StrDup(), StrReverse() - .NET: selber schreiben.
      • Switch() - .NET: Switch benutzen bzw. While oder For
      • SYD() - .NET: selber berechnen.
      • SystemTypeName() - .NET: unnötig
      • TypeName() - .NET: .GetType.Name/FullName()
      • UBound() - .NET: Array.GetUpperBound()
      • UCase() - .NET: String.ToUpper()
      • Val() - .NET: explizite Typkonvertierung durchführen (z.B. .ToString())
      • VarType(), VbTypeName() - .NET: unnötig.

      Böse Operatoren:
      • logisches VB-Like Or/And: Die Operatoren überprüfen immer beide Ausdrücke, auch wenn der erste schon ein Ergebnis liefert, welches den zweiten unnötig macht. Richtig: OrElse/AndAlso: Diese machen es richtig. And und Or sind allerdings hilfreich, wenn der zweite/beide Ausdruck/Ausdrücke aus Funktionsaufrufen besteht und diese ausgeführt werden sollen, egal, wie das Ergebnis lautet.
      Verhindern, in die Falle zu tappen:
      EDR hat dazu einen Artikel geschrieben: vb-paradise.de/t/91397-


      Wer noch etwas hinzufügen möchte oder bemerkt, dass etwas nicht stimmt, einfach eine PN an mich!

      lg SeriTools
      | Keine Fragen per PN oder Skype.

      Dieser Beitrag wurde bereits 29 mal editiert, zuletzt von „SeriTools“ ()

      Hi
      Chr, ChrW, AscW, Asc, CInt, CUInt, CLng, CULng, CShort, CUShort, CSByte, CByte, CSng, CDbl (waren das alle?) sind soweit ich weiß konstant und werden vom Compiler anders gehandhabt. So funktioniert beispielsweise

      VB.NET-Quellcode

      1. Public Const EXAMPLECHARACER As Char = Chr(9)

      aber nicht

      VB.NET-Quellcode

      1. Public Const EXAMPLECHARACER As Char = Convert.ToChar(9)

      In C# gibts dafür dann (char)(integerWert) und auch Convert.ToChar(9) funktioniert. Weiß nicht, obs in späteren Versionen in VB möglich ist, aber in Visual Studio 2008 ist das zumindest so.

      Gruß
      ~blaze~
      CStr() etc. sind wohl so Zwischendinge. Übergibt man einen konstanten Wert, wird sofort der konvertierte Wert direkt im Programm gespeichert, deshalb funktioniert das auch mit Const. Übergibt man einen variablen Wert, wird das ganze zu einer Funktion.

      lg SeriTools
      | Keine Fragen per PN oder Skype.
      Hi,

      beim Betrachten des OpCodes fällt auf, dass konstante Werte direkt in den Code geschrieben werden, ohne jegliche verweise auf Variablen. Sollte man eine Konstante jetzt mit einer Funktion definieren, könnten aus dieser Funktion jedes mal unterschiedliche Werte herauskommen. Somit wäre der Sinn einer Konstanten nicht getroffen.
      (Ich glaub das ist fast wie das #Define-Schlüsselwort des Preprocessors in C?)

      Zu konstanten Chars:
      In C# geht es so:

      Quellcode

      1. Char c = '\u0009';
      Man kann dort einen HEX-Wert angeben.
      Der Konverter zu VB.NET sagt dazu folgendes:

      VB.NET-Quellcode

      1. Dim c As [Char] = ControlChars.Tab


      Sollte somit ein konstanter Ausdruck sein.

      VB.NET-Quellcode

      1. Public Const CharKonstante as Char = ControlChars.Tab
      Müsste also funktionieren.
      Von meinem iPhone gesendet

      Dieser Beitrag wurde bereits 3 mal editiert, zuletzt von „nikeee13“ ()

      Meinte eher so Coding-Richtlinien, dass man in neuen Projekten VB6-Funktionen nicht mehr benutzen soll, nur in Portierungen. Stand mal in irgendeinem MSDN-Artikel.

      Chr, ChrW, AscW, Asc, CInt, CUInt, CLng, CULng, CShort, CUShort, CSByte, CByte, CSng, CDbl werden wohl vom Compiler für konstante Werte anders behandelt (es wird direkt der konvertierte Wert gespeichert) und sind dort wohl vorzuziehen. Werde es mal als Hinweis einfügen.

      Gibt es noch weitere solche Fälle? Wenn ja, bitte hier darüber berichten!

      lg SeriTools
      | Keine Fragen per PN oder Skype.

      ~blaze~ schrieb:

      Übrigens ist ControlChars ein Modul aus der Microsoft.VisualBasic-Dll, dachte ich?
      Mich würde mal interessieren, wie man in VB ein C#-'\u0009' angeben würde.

      die IIF-Funktion gibt übrigens immer einn Object zurück, deshalb sollte man richtig casten:

      VB.NET-Quellcode

      1. Private Sub Test1()
      2. Dim b as boolean = true
      3. Dim a As Integer = CInt(IIf(b, 1, 0))
      4. End Sub
      5. Private Sub Test2()
      6. Dim b as boolean = true
      7. Dim a As Integer = If(b, 1, 0)
      8. End Sub


      Beim Betrachten des OpCodes fällt auf

      Quellcode

      1. .method private static void Test1() cil managed
      2. {
      3. .maxstack 3
      4. .locals init (
      5. [0] int32 a,
      6. [1] bool b)
      7. L_0000: nop
      8. L_0001: ldc.i4.1
      9. L_0002: stloc.1
      10. L_0003: ldloc.1
      11. L_0004: ldc.i4.1
      12. L_0005: box int32
      13. L_000a: ldc.i4.0
      14. L_000b: box int32
      15. L_0010: call object [Microsoft.VisualBasic]Microsoft.VisualBasic.Interaction::IIf(bool, object, object)
      16. L_0015: call int32 [Microsoft.VisualBasic]Microsoft.VisualBasic.CompilerServices.Conversions::ToInteger(object)
      17. L_001a: stloc.0
      18. L_001b: nop
      19. L_001c: ret
      20. }

      Quellcode

      1. .method private static void Test2() cil managed
      2. {
      3. .maxstack 1
      4. .locals init (
      5. [0] int32 a,
      6. [1] bool b)
      7. L_0000: nop
      8. L_0001: ldc.i4.1
      9. L_0002: stloc.1
      10. L_0003: ldloc.1
      11. L_0004: brtrue.s L_0009
      12. L_0006: ldc.i4.0
      13. L_0007: br.s L_000a
      14. L_0009: ldc.i4.1
      15. L_000a: stloc.0
      16. L_000b: nop
      17. L_000c: ret
      18. }

      Der Sub Test2 ist (etwas) optimierter als Test1. Was hier nicht auffällt, ist, dass konstante Ausdrücke bei If() vom Compiler wegoptimiert werden. Bei IIf nicht.

      Der Decompiler übersetzt den Test1 übrigens so

      Quellcode

      1. private static void Test1()
      2. {
      3. bool b = true;
      4. int a = Conversions.ToInteger(Interaction.IIf(b, 1, 0));
      5. }


      Übersetze Version vom Test2 Decompiler nach C#

      Quellcode

      1. private static void Test2()
      2. {
      3. bool b = true;
      4. int a = b ? 1 : 0;
      5. }


      Der C# Test2-Void

      Quellcode

      1. void Test2Cs()
      2. {
      3. bool b = true;
      4. int a = b ? 1 : 0;
      5. }


      Und der OpCode von der C#-Version des Voids Test2

      Quellcode

      1. .method private hidebysig instance void Test2Cs() cil managed
      2. {
      3. .maxstack 2
      4. .locals init (
      5. [0] bool b,
      6. [1] int32 a)
      7. L_0000: nop
      8. L_0001: ldc.i4.1
      9. L_0002: stloc.0
      10. L_0003: ldloc.0
      11. L_0004: brtrue.s L_0009
      12. L_0006: ldc.i4.0
      13. L_0007: br.s L_000a
      14. L_0009: ldc.i4.1
      15. L_000a: stloc.1
      16. L_000b: ret
      17. }
      Von meinem iPhone gesendet

      Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „nikeee13“ ()

      Nein, das sind andere Funktionen. Die alten Dateioperationen zum Beispiel benutzen ein ganz anderes System als alles aus System.IO. Sicherlich werden einige der Funktionen durch "normale" Funktionen realisiert, doch es findet kein "Suchen & Ersetzen" in dem Quellcode statt (Ausnahme CChar,CStr usw. bei der Konvertierung von Literalen). Weiteres siehe den ersten Abschnitt im Startpost: "Warum sollte man die VB6-Funktionen nicht weiterverwenden?"

      lg SeriTools
      | Keine Fragen per PN oder Skype.
      Das hat nichts mit der IDE zu tun, mehr mit dem Framework.
      MS hat die alten Funktionen drinnen gelassen, um Abwärtskompatiblität zu gewährleisten.
      Meiner Meinung nach nicht wirklich sinnvoll, aber was will man machen. Irgendwann fliegen sie hoffentlich raus.
      Bzgl. einer PN zu diesem Thread:

      Kevin Hombre schrieb:

      Hey,

      ich guck öfters mal deinen Thread an, wenn ich mir unsicher bin:


      [VB 2010] "Böse" VB6/VB 2003-Funktionen - und ihre "guten"/besseren neuen VB.NET-Alternativen

      Wie sieht das aus mit typeof ? Konnte ich im Thread nicht finden.
      Handelt es sich bei typeof auch um eine böse Funktion? Wenn Ja, bitte nachtragen. Danke!

      Directcast ebenso, konnte ich auch nicht finden. Man nutzt heutzutage Ctype.

      Achja: Wie siehts mit isnot Nothing aus?


      Meine Antwort:
      Zu allererst, warum ist die gesamte PN fettgedruckt?

      Kevin Hombre schrieb:

      Wie sieht das aus mit typeof ? Konnte ich im Thread nicht finden.
      Handelt es sich bei typeof auch um eine böse Funktion? Wenn Ja, bitte nachtragen. Danke!

      TypeOf ist keine VB6-Funktion, sie gehört zum normalen VB.NET-Befehlsumfang dazu. (In VB6 wurde sowieso wenig auf Typen geachtet, in VB.NET hat man eine strikte Typenprüfung durch Option Strict On)
      Übrigens kann eine Funktion nur wirklich veraltet sein, wenn es auch eine neue Alternative gäbe, für TypeOf gibts afaik keine.

      Kevin Hombre schrieb:

      Directcast ebenso, konnte ich auch nicht finden. Man nutzt heutzutage Ctype.

      Das ist einfach grundsätzlich falsch. DirectCast ist wie CType ein wesentlicher Teil des VB.NET-Befehlsumfangs. Beide werden für verschiedene Sachen verwendet. DirectCast funktioniert nur bei Typen, die voneinander erben, dafür ist DirectCast WESENTLICH schneller als CType (google es einfach mal). CType steht für ConvertType und nicht CastType (falls dir der Unterschied nicht klar ist, informier dich) und konvertiert jeden Typ mit entsprechenden Konvertierfunktionen in einen anderen.

      Beispiel für DirectCast: Du bekommst von irgendeiner Funktion einen Stream zurück, von dem du weißt, dass es ein FileStream ist. Doch du kannst auf die FileStream-eigenen Member nicht zugreifen, da es für den Compiler/für VS nicht ersichtlich ist, dass es ein FileStream ist. Um ihm zu sagen, "das is tein FileStream", musst du den Stream casten:
      Dim kgwk As FileStream = DirectCast(blarge.GetStream(), FileStream)
      Danach kannst du auch auf die FileStream-eigenen Member zugreifen.

      CType: CType(gaenr.GetType1(),Type2)
      Sofern Type1 und/oder Type2 eine Konvertierfunktion für den jeweils anderen Typ bereitstellt, kann CType diese konvertieren. Darüber hinaus kann CType aber auch casten. Diese ganzen Überprüfungen machen CType aber dafür wesentlich langsamer.

      ==> Also nein, es ist keine böse Funktion.

      Kevin Hombre schrieb:

      Man nutzt heutzutage Ctype.

      Sei etwas vorsichtiger mit solchen allgemeinen Aussagen, die können oft falsch sein. DirectCast, TryCast und CType gibt es allesamt erst seit VB.NET. ( msdn.microsoft.com/de-de/library/7k6y2h6x.aspx )

      Kevin Hombre schrieb:

      Achja: Wie siehts mit isnot Nothing aus?

      Schlecht, IsNot ist der ganz einfache negierende Äquivalenzoperator, genauso wie es in C# != ist.
      Warum man deiner Meinung nach diesen nicht in Zusammenhang mit Nothing benutzen soll verstehe ich auch nicht. Zu überprüfen, ob eine Referenzvariable zugewiesen wurde, bevor man auf deren Member zugreift, um eine NullReferenceException zu verhindern gehört zu einer guten Programmierung einfach dazu. Und das soll in die Liste der "bösen" Funktionen? Eher nicht.
      Ob man var IsNot Nothing, Not var Is Nothing oder var Is Nothing = False verwendet, der Compiler macht ein und denselben IL-Code daraus.
      Es gibt dabei aber eine wichtige Ausnahme: Die Funktion IsNothing() aus dem Microsoft.VisualBasic ist in der Tat eine "böse" Funktion. Diese befindet sich in der Liste unter dem Punkt:
      IsArray(), IsDate(), IsDBNull(), IsNumeric() etc. - .NET: Typvergleich ausführen, evtl. TryParse(), falls verfügbar

      Bei IsNothing trifft die erste Alternative zu: Typvergleich ausführen. Der Operator dafür ist "Is". ==> var Is Nothing
      ==> Wenn man das Gegenteil herausfinden will eben noch ein "Not" hinzufügen.
      | Keine Fragen per PN oder Skype.
      Schlecht, IsNot ist der ganz einfache negierende Äquivalenzoperator, genauso wie es in C# != ist.
      Dabei muss man etwas anmerken:
      IsNot und Is überprüfen auf Referenzgleichheit. Beispiel:

      VB.NET-Quellcode

      1. Dim a = "Hallo", b = "Hallo"
      2. If a Is b Then
      3. Debug.Print("Ist gleich!")
      4. Else
      5. Debug.Print("Ist ungleich!")
      6. End If
      7. ' Ausgabe: Ist ungleich!
      a und b sind zwar gleich, jedoch nicht dasselbe Objekt.
      Der =-Operator, wenn als Vergleichsoperator angewendet, überprüft grundsätzlich auch auf Referenzgleichheit, Selbiges gilt auch für die Equals-Methode.
      Da jedoch sowohl der =-Operator als auch die Equals-Methode überladen werden können, hängt es vom Typ ab, was genau da überprüft wird.
      Bei String überprüfen Equals und = auf Wertgleichheit:

      VB.NET-Quellcode

      1. Dim a = "Hallo", b = "Hallo"
      2. If a = b AndAlso a.Equals(b) Then
      3. Debug.Print("Ist gleich!")
      4. Else
      5. Debug.Print("Ist ungleich!")
      6. End If
      7. ' Ausgabe: Ist gleich!
      Es gibt einen Punkt wo ich eine Anmerkung dazu habe:

      Split() - .NET: String.Split()

      Damit reitest du einige Personen in einen Fehler, wenn diejenigen zuvor mit Split(_String, vbCrLf) bei Zeilenumbrüchen Ihren String gesplittet hatten.
      Und davon ausgehen, dass sich .Split genauso verhält, wie Split(.

      The Split Runtime function will split on a single character or a string. The String.Split function will only split on a single character, so if you try to split on CR-LF it will split on the CR and leave the LF behind. To split on a string without Runtime functions, use Regex.Split:

      VB.NET-Quellcode

      1. Option Explicit On
      2. Option Strict On
      3. Imports System.Text.RegularExpressions
      4. Dim lines As String() = System.Text.RegularExpressions.Regex.Split(myString, Environment.NewLine)
      5. '// oder:
      6. Dim lines As String() = System.Text.RegularExpressions.Regex.Split(myString, vbCrLf)

      Anderenfalls würdest du etwas in diese Richtung bekommen und dann erstmal den Fehler suchen dürfen:

      Input:

      Quellcode

      1. hanspeter
      2. rudiheinz
      3. ralfones

      Quellcode

      1. "hanspeter" & vbCrLf & "rudiheinz" & vbCrLf & "ralfones"

      Output:

      Quellcode

      1. "hanspeter"
      2. "" & vbLf & "rudiheinz"
      3. "" & vbLf & "ralfones"

      Dieser Beitrag wurde bereits 2 mal editiert, zuletzt von „FireEmerald“ ()

      Das ist so aber nicht richtig, auch String.Split erlaubt das Splitten an einem String, siehe diese Überladung:
      msdn.microsoft.com/de-de/library/tabh47cf(v=vs.110).aspx
      Ist halt gleich ein String-Array, da muss man dann halt ein Array mit nur einem Element übergeben. Zu beachten ist auch, dass man einen StringSplitOptions-Enumerationswert mitübergeben muss, weils keine Überladung ohne gibt, finde ich persönlich zwar komisch, ist aber nicht wirklich schlimm.

      FireEmerald schrieb:

      Und davon ausgehen, dass sich .Split genauso verhält, wie Split(.

      Es geht doch in diesem Thread genau darum, dass Leute nicht alte Funktionen mit gammligen Funktionsweisen und Rückgabewerten benutzen... Natürlich funktioniert String.Split anders, weils funktionsfähiger ist.
      | Keine Fragen per PN oder Skype.