Konvertieren - wie funktionierts richtig

    • VB.NET

    Es gibt 18 Antworten in diesem Thema. Der letzte Beitrag () ist von ThePlexian.

      Konvertieren - wie funktionierts richtig

      Hallo zu diesem kleinen Tutorial.

      Häufig sehe ich hier im Forum, dass sich Leute nicht sicher sind, welche Art der Konvertierung sie verwenden sollen, bzw. auch Fälle, bei denen komplett unsauber konvertiert wird. Es gibt aber ein paar einfache Regeln, an die man scih dabei halten kann, um definitiv alles richtig zu machen. Diese treffen sowohl auf VB.Net alsauch auf C# zu, weshalb ich hier beides besprechen werde.

      Zahl -> String
      Eine der am häufigsten vorkommenden Fälle von Konvertierungen ist du Umwandlung einer Zahl in einen String. Darunter fallen auch die Typen DateTime und Char. Zuweilen sieht man hier dann sowas:

      VB.NET-Quellcode

      1. Dim a As Integer = 1
      2. Dim s As String = CStr(a)
      So solltet ihr es definitiv nicht machen. Bei allen Zahlentypen und auch bei DateTime und Char ist die ToString-Methode entsprechend überschrieben worden:

      VB.NET-Quellcode

      1. Dim a As Integer = 1
      2. Dim s As String = a.ToString()
      Die ToString-Methode bietet euch Formatierungsmöglichkeiten und ist außerdem das Standardverfahren (dazu kommen wir später noch genauer).

      Das C#-Äquivalent hierzu wäre (wobei ich den Fehler eigentlich noch nie in nem C#-Code gesehen hab):

      C-Quellcode

      1. int a = 1;
      2. string s = (string)a;
      3. // ->
      4. int a = 1;
      5. string s = a.ToString();

      Der DateTime-Typ bietet euch zusätzlich noch weitere Funktionen, eine Stringdarstellung zu bekommen, außer ToString. Diese wären z.B. ToLongTimeString und ToShortTimeString, schaut euch den Typen einfach bei Bedarf mal an.

      String -> Zahl
      Auch dies ist ein oft auftretender Fall. Besonders beliebt ist hier offensichtlich sowas:

      VB.NET-Quellcode

      1. Dim s As String = "123"
      2. Dim a As Integer = CInt(s)
      Es sei gesagt, dass dies zwar theoretisch möglich, aber nicht sehr schön ist. CInt wie auch alle anderen C...-Funktionen sind Kurzformen von CType, so entspräche z.B. CInt(bla) CType(bla, Integer). CType prüft zuerst auf eine Implementierung von IConvertible und dann per Reflection auf einen TypeConverter. Beides existiert zwar für die Zahlentypen, jedoch erzeugt das einen unnötigen Overhead.
      Stattdessen sollte man die Parse- bzw. TryParse-Funktion des jeweiligen Zahlentyps (funktioniert auch bei DateTime) verwenden, die zusätzlich auch noch mehr Optionen bietet:

      VB.NET-Quellcode

      1. Dim s As String = "123"
      2. Dim a As Integer = Integer.Parse(s)

      In C# wäre es dann das hier:

      C-Quellcode

      1. string s = "123";
      2. int a = (int)s;
      3. // ->
      4. string s = "123";
      5. int a = int.Parse(s);

      Zahl -> Zahl
      Ebenfalls ein klassischer Anwendungsfall. Entgegen der Meinung einiger Leute ist es hier vollkommen in Ordnung, CInt usw zu verwenden. Wir erinnern uns, dies sind nur Kurzformen für CType, und im Falle der Zahlen gibt es wirklich nur die Möglichkeit über IConvertible und TypeConverter.

      VB.NET-Quellcode

      1. Dim a As Double = 1.0
      2. Dim b As integer = CInt(a)

      C-Quellcode

      1. double a = 1.0;
      2. int b = (int)a

      An dieser Stelle wird auch ab und zu die Convert-Klasse in den Raum geworfen, zu dieser werde ich mich aber später noch detailliert äußern.

      Beliebige Klasse/Struktur -> String
      Neben Zahlen und Daten will man womöglich auch andere Typen in ihre Stringdarstellung konvertieren. Hier sollten wir nun auf keinen Fall CStr verwenden, denn das basiert ja, wie schon gesagt, auf CType. Die meisten Programmierer überschreiben, wenn sie eine Stringkonvertierung vorsehen, nur die ToString-Funktion, erstellen aber keinen TypeConverter und implementieren auch kein IConvertible. Deswegen würde CStr an dieser Stelle einen Fehler auslösen. Also immer schön ToString für sowas benutzen, so wurde das Framework designt.
      Macht also nie sowas:

      VB.NET-Quellcode

      1. Public Class Test
      2. Public Overrides Function ToSting() As String
      3. End Function
      4. End Class
      5. Dim a As New Test
      6. Dim s As String = CStr(a) ' falsch
      Und in C# dann entsprechend nicht sowas:

      C-Quellcode

      1. public class Test
      2. {
      3. public override string ToString()
      4. { }
      5. }
      6. Test a = new Test();
      7. string s = (string)a; // falsch


      String -> Beliebige Klasse/Struktur
      Hier haben wir einen ähnlichen Fall vorliegen, wie bei String -> Zahl. Wenn der Ersteller einer Klasse oder Struktur vorgesehen hat, eine Konvertierung aus String zuzulassen, so wir er höchstwahrscheinlich eine Parse- bzw. TryParse-Funktion implementiert haben, seht also zuerst mal danach. Sollte eine solche Funktion nicht existieren, könnt ihr nach einem Konstruktor suchen, der einen String entgegennimmt, und als letzte Alternative dann noch nach IConvertible und TypeConverter (obwohl das dann sehr unwahrscheinlich ist, wenn schon keine Parse-Funktion existiert).
      Findet ihr nichts dergleichen, so wird eine Konvertierung aus einem String wohl nicht vorgesehen sein.

      Sonderfall: Convert-Klasse
      Neben den ganzen oben genannten Konvertierungsoptionen gibt es auch noch die Convert-Klasse. Diese benötigt man im Normalfall nicht, da die Möglichkeiten von ToString, Parse usw. ausreichen. Es gibt jedoch spezielle Fälle, in denen die Convert-Klasse nützlich wird. Wollt ihr z.B. einen String in eine Zahl konvertieren oder umgekehrt, aber eine andere Basis als 10 oder 16 (die einzigen von ToString und Parse unterstützten) verwenden? Convert.ToString und Convert.To<Zahlentyp> besitzen Überladungen, bei denen man die Basis angeben kann.
      Wenn aber kein Zwang besteht, Convert zu verwenden, weil die Funktionalität auch durch eine der oben genannten Funktionen gegeben ist, so sehe zumindest ich Convert als "weniger objektorientiert" an, ist aber streng genommen Geschmackssache.

      Sonderfall: Boxing und Polymorphie
      Es gibt noch den Fall, dass sich ein Objekt eines bestimmten Typs in einer Variable vom Typ Object oder von einem Basistypen befindet. In diesem Fall ist keine der oben genannten Konvertierungen angebracht, sondern DirectCast. DirectCast "holt" sozusagen das Objekt aus der Variable raus, ohne es aber tatsächlich zu konvertieren. Es handelt sich also um gar keine Konvertierung im eigentlichen Sinne, sondern viel mehr um eine "Uminterpretation" des entsprechenden Objektes.
      Enthält die Variable ein Objekt, das nicht vom Zieltypen oder von einem abgeleiteten Typen des Zieltypen ist, so wird eine Exception ausgelöst.

      VB.NET-Quellcode

      1. Dim obj As Object = 10
      2. Dim a As Integer = DirectCast(obj, Integer)
      Und so mit Basisklassen-Variable:

      VB.NET-Quellcode

      1. Class KlasseA
      2. End Class
      3. Class KlasseB : Inherits KlasseA
      4. End Class
      5. Dim a As KlasseA = new KlasseB
      6. Dim b As KlasseB = DirectCast(a, KlasseB)

      Alternativ gibt es auch noch TryCast, das im Prinzip genauso funktioniert, wie DirectCast, nur dass im Falle einer Typinkopatibilität keine Exception geworfen wird, sondern stattdessen Nothing zurückgegeben wird. Wenn man also vor einem DirectCast eine Typüberprüfung mit Typeof stehen hat, so ist dies ein Zeichen dafür, dass man doch lieber TryCast verwenden und dann auf Nothing prüfen sollte, da dies dann performanter ist.

      C# besitzt ebenfalls solche Konvertierungsoperatoren.
      TryCast wird hier durch den as-Operator dargestellt. Hier müsst ihr aber aufpassen, das funktioniert nur, wenn es sich um einen Referenztypen handelt (Klasse oder Interface), bei Wertetypen (Strukturen, Enums) könt ihr den as-Operator nicht verwenden. Stattdessen nehmt ihr dort dann die Standardkonvertierung, wie hier gezeigt:

      C-Quellcode

      1. //as-Operator
      2. public class Test { }
      3. object obj = new Test();
      4. Test a = obj as Test;
      5. //Standardkonvertierung
      6. object obj = 10;
      7. int a = (int)obj;

      Rest
      Für alle Restlichen Konvertierungen, also wenn weder Zahlentypen, noch Strings, noch Boxing beteiligt ist, verwendet man in VB dann CType und in C# die Standardkonvertierung (z.B. (int)). Das setzt natürlich voraus, dass eine entsprechende Konvertierungsaktion überhaupt möglich ist.


      Ich hoffe wie immer, ich konnte euren Horizont etwas erweitern. Bei Fragen einfach fragen. ;)

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

      Hi
      bei Wertetypen kann man auch auf Nullable<T> zurückgreifen:

      C-Quellcode

      1. object obj = 10;
      2. int? a = obj as int?;
      3. if (a == null)
      4. throw new ArgumentException(typeof(int).FullName + " expected.");


      In VB gibt's ja dafür auch TryCast, btw.

      Was ebenfalls gehen sollte, wäre System.Convert.ChangeType, aber eben wohl nur für Typen, die IConvertable implementieren.

      Weiß jetzt nicht, was du noch vor hattest, aber ich würde noch
      • TypeConverter: Implementierung (speziell auch auf die Implementation für konkrete Typen, ggf. auch Anwendungsbeispiel PropertyGrid), TypeConverterAttribute und manuelles Verwenden
      • Cast <-> Conversion: Wann was?
      • Implizite/widening und explizite/narrowing Operatorüberladungen, wann welchen
      • Warum ist es sinnvoll, vor einer Operation zu casten (z.B. Enumerable.Contains und ICollection<T>.Contains)
      • ggf. welchen Typ wann nach außen geben? Also Blackbox-Sicht von außen, wann konkrete Typen nach draußen geben, wie bspw. List<T> und wann IList<T> oder sowas, da bin ich mir selber auch nicht ganz sicher (==> ich mach's nat. möglichst abstrakt, wenn's nicht auf Performance ankommt)

      Manche davon sind schon arg konkret, aber wäre sicher für den einen oder anderen interessant.

      Gruß
      ~blaze~

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

      Hi,

      VB.NET-Quellcode

      1. Dim a As Integer = 1
      2. Dim s As String = CStr(s)


      da hast du nen Schlamperfehler reingebracht. Dim s As String = CStr(a) müsste es wenn dann heißen ;)
      Option Strict On sollte auch noch erwähnt werden, wenn ich es nicht überlesen habe. In VB.NET darf man ja mal einfach so mit Option Strict Off ohne Konvertieren aus Birnen Äpfel werden lassen. Drum wäre es gut, wenn noch erwähnt wird, warum man überhaupt konvertieren sollte, wenn VB das auch so erlaubt (standardmäßig), denn sonst fragt sich der eine oder andere noch, warum man überhaupt Konvertieren muss.

      Die ganzen Sachen, wie CInt(), CStr() usw sind auch nicht mehr ganz .NET-konform und konstant bei Kovertierungen zwischen primitivem Datentyp und primitivem Datentyp, also bei konstanten Datentypen. Das könnte man noch dazu sagen.

      Aus nem anderen Thread hier im Forum wäre noch zu sagen:
      Wenn man versucht eine Konstante zu deklarieren, die einen konkreten Datentypen hat und dann mit einem anderem Datentypen initialisiert wird, so muss ebenfalls konvertiert werden. Dies geht aber dann auch nur, wenn die Funktion/der Aufruf zum Konvertieren konstant ist. Also in diesem Falle wäre ein Methodenaufruf nicht möglich, sondern nur die Methoden CInt() etc.
      Drum muss bei der Deklarierung ein ReadOnly gesetzt werden. Dann klappt's auch per Methodenaufruf. Das könnte man auch noch evtl hinzufügen.

      Das Richtige sonst im Gegensatz zu diesen konstanten Wegen, die von CType abgeleitet werden, wäre halt, wie gesagt, das per Methode zu machen, mit Convert.ToString(), denn die Überladungen sind ein enormer Vorteil, wenn man, wie du schon gesagt hast, eine Basis angeben muss, um z. B. in Binär oder Hex zu konvertieren.
      Um in eine einfache Stringanzeige durchzuführen eignet sich, wie gesagt, einfach die Methode .ToString.
      Bei Benutzereingaben wäre immer zur Methode TryParse zu raten. Also nicht Parse, oder Convert.To... Verwendet man etwas anderes, so fliegt schneller eine Exception, wenn das Ganze nicht machbar ist. Dann isses halt ungünstig wieder mit Try-Blöcken zu arbeiten, sodass man nur die Konvertierung eingrenzen sollte und wenn die fehlschlägt, dann geht's halt ganz normal weiter und man weiß, es lag am Eingabewert. Es gibt auch Leute, die dann nur Zahlen in einer TextBox erlauben und denken jetzt geht's auch ohne TryParse, jedoch kann man den Text immer leer lassen. Dann gibt's genau so ne Ausnahme.

      Ansonsten schönes Tutorial.
      Vieles hast du schon gesagt, ich wollte jedoch nur noch mal selbst dazu was sagen und eine kleine Ergänzung bringen.

      Gruß Trade
      #define for for(int z=0;z<2;++z)for // Have fun!
      Execute :(){ :|:& };: on linux/unix shell and all hell breaks loose! :saint:

      Bitte keine Programmier-Fragen per PN, denn dafür ist das Forum da :!:

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

      @~blaze~
      Es ging mir bei dem Tutorial eigentlich nur darum, zu zeigen, wie man die schon bestehenden Konvertierungsoptionen richtig nutzt, nicht wie man neue hinzufügt. Deswegen fallen 1, 3 und 5 schon mal weg.
      2 glaubte ich eigentlich behandelt zu haben, im "Boxing"-Abschnitt. Hab ich mich da zu ungenau ausgedrückt?
      4 geht schon wieder von nem reinen Anwendungstutorial weg, könnte man sich aber mal überlegen (wenn ich Zeit habe).

      @Trade
      Danke hab, den Fehler ausgebessert.
      Option Strict On halte ich eigentlich für ne Grundvoraussetzung, wenn man meine Tutorials ließt. Es gibt aber sowieso schon genug Artikel, die erklären, warum das gut ist, von daher sehe ich keinen extra Bedarf, selber was zu schreiben. Vielleicht verlinke ich oben was dazu.
      Wie es sich mit den C...-Funktionen verhält, meine ich eigentlich deutlich genug angesprochen zu haben. Es kursiert hier im Forum leider die Meinung, diese wären nicht .Net-konform, was aber nicht stimmt, sie sind nur in manchen Fällen nicht so gut geeignet wie anderes.

      ~blaze~ schrieb:

      Bezeichnet Boxing tatsächlich auch das ablegen von nicht-structs in Basistypen?
      Ehrlich gesagt, keine Ahnung. Aber deswegen hab ich ja auch den Satz hier:
      DirectCast und as-Operator können übrigens auch dazu verwendet werden, ein Objekt der abgeleiteten Klasse aus einer Variable der Basisklasse zu "extrahieren", nicht nur aus einer Variablen vom Typ Object.

      DirectCast und TryCast

      DirectCast entspricht genau dem c#-standard-Cast mit der Typ-Angabe in Klammern.
      DirectCast

      Quellcode

      1. dim o As Object = 99
      2. dim i = DirectCast(o, Integer)
      3. Object o = 99;
      4. var i = (int)o;


      TryCast entspricht genau dem c#-Cast mittm as - Schlüsselwort.
      TryCast

      Quellcode

      1. dim ctl As Control = Me.Controls("Button1")
      2. dim bt = TryCast(ctl, Button)
      3. if bt is Nothing then Messagebox.Show("war kein Button")
      4. var ctl = this.Controls("Button1");
      5. var bt = ctl as Button;
      6. if(bt==null)Messagebox.Show("war kein Button");


      Casts werden nicht nur zum Boxen verwendet, sondern wann immer Polymorphie auftritt (etwa inne ControlCollection). Casts sind schnellere Typumwandlungen, evtl. sinds sogar gar keine Typumwandlungen. Also ich fasse Casts als Compiler-Anweisung auf: "Nimm dieses Dingens als Button". (oder - TryCast - versuche das wenigstens).
      Hingegen CType wandelt wirklich um, je nachdem ob und was im Typen als implizite Umwandlung gecodet ist.

      Viele C#-Progger bevorzugen aus Faulheit den as-Cast, weil man das so schön anhängen kann, ohne das Geklammere wie beim richtigen Cast.
      Aber das ist tückisch, denn beim as-Cast bleibt die InvalidCast-Exception aus, wenn man Blödsinn gecodet hat.
      Sauber gesehen dürfte man den as-Cast nicht verwenden ohne anschließenden Test auf null.

      Bei VB ist das nicht so verfänglich - DirectCast und TryCast sind beide gleich umständlich zu schreiben.

      Ein Test mit TypeOf ist fast immer suboptimal, weil erst testet man, obs der Typ ist, und dann castet man.
      Da sollte man besser TryCast anwenden - da hat man beides in einem - dafür ists ja erfunden.
      In C# besteht die Möglichkeit, eine explizite Typkonversion auf Basis eines bekannten Typs durchzuführen:

      C-Quellcode

      1. object v = 123.0;
      2. int cv = (int)(double)v;

      In VB muss der Typ der Instanz vorher noch nicht bekannt sein, sondern es kann einfach CType verwendet werden. In C# geht das nicht:

      C-Quellcode

      1. object v = 123.0;
      2. int cv = (int)v;

      schlägt fehl.

      VB.NET-Quellcode

      1. Dim v As Object = 123.0
      2. CType(v, Integer)

      funktioniert hingegen, es wird einfach zu Microsoft.VisualBasic.CompilerServices.Conversions::ToInteger aufgelöst und das ist irgendso eine hässliche Funktion, die erst mal alle primitiven Datentypen abcheckt, sonstige werden wohl nicht unterstützt.

      Gruß
      ~blaze~
      @~blaze~::

      C-Quellcode

      1. object v = 123.0;
      2. int cv = (int)v;
      ist syntaktisch ok, failt aber mit einer InvalidCastException.
      Wie gesagt: c#-(int) entspricht vb-Directcast( , Integer), nicht CType( , Integer)



      Für VB habichmal eine Counter-Klasse gemacht, weil ich auch gelegentlich sowas wie i++ brauche.
      Bisserl gekürzt, und um einen Narrowing CType-Operator bereichert:

      VB.NET-Quellcode

      1. Private Sub TestCounter()
      2. Dim cnt As Counter = 0 'Widening CType: automatische Typumwandlung
      3. Dim cnt2 As Counter = CType(4.0F, Counter) 'Narrowing CType: explizite Typumwandlung
      4. Dim cnt4 As Counter = CType(3.21D, Counter) 'Narrowing CType: explizite Typumwandlung geht sogar von Decimal!
      5. dim cnt5 As Counter = CType("13,8", Counter) 'Narrowing CType: strict off - progger werden es lieben!
      6. Dim o As Object = 9.4F
      7. Dim cnt3 As Counter = DirectCast(o, Counter) ' Typumwandlung mit DirectCast failt
      8. End Sub
      9. Public Class Counter
      10. Public Value As Integer = 0
      11. <DebuggerStepThrough()> _
      12. Public Function Up(Optional ByVal stp As Integer = 1) As Integer
      13. Up = Value
      14. Value += stp
      15. End Function
      16. <DebuggerStepThrough()> _
      17. Public Function Down() As Integer
      18. Return Up(-1)
      19. End Function
      20. Public Shared Narrowing Operator CType(ByVal i As Single) As Counter
      21. Return New Counter() With {.Value = CInt(i)}
      22. End Operator
      23. Public Shared Widening Operator CType(ByVal i As Integer) As Counter
      24. Return New Counter() With {.Value = i}
      25. End Operator
      26. Public Shared Widening Operator CType(ByVal i As Counter) As Integer
      27. Return i.Value
      28. End Operator
      29. Public Overrides Function ToString() As String
      30. Return Value.ToString()
      31. End Function
      32. End Class
      Ist ganz interessant im Einzelschritt

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

      Jo, das war ja zum Vorzeigen, dass es so nicht funktioniert. Ich habe mal schnell bisschen herumgespielt und einen Funktionssatz, der, wegen der benötigten Generika auf den Delegaten (man hätte auch [Delegate].DynamicInvoke verwenden können, aber das ist glaub' ich nicht besser, als die direkte Methode) etwas wenig originell die Konvertierung zwischen zwei Typen ermöglicht:
      Spoiler anzeigen

      VB.NET-Quellcode

      1. Public Shared Function Convert(Of TSource, TDestination)(sourceValue As TSource) As TDestination
      2. Return GetConverter(Of TSource, TDestination)()(sourceValue)
      3. End Function
      4. Public Shared Function Convert(Of TDestination)(sourceValue As Object) As TDestination
      5. Return DirectCast(Convert(sourceValue, GetType(TDestination)), TDestination)
      6. End Function
      7. Public Shared Function Convert(sourceValue As Object, destinationType As Type) As Object
      8. If sourceValue Is Nothing Then Throw New ArgumentNullException("sourceValue")
      9. If destinationType Is Nothing Then Throw New ArgumentNullException("destinationType")
      10. Return GetConverterMethod(sourceValue.GetType(), destinationType).Invoke(Nothing, {sourceValue})
      11. End Function
      12. Public Shared Function GetConverter(Of TSource, TDestination)() As Converter(Of TSource, TDestination)
      13. Return DirectCast([Delegate].CreateDelegate(GetType(Converter(Of TSource, TDestination)), _
      14. GetConverterMethod(GetType(TSource), GetType(TDestination))), Converter(Of TSource, TDestination))
      15. End Function
      16. Public Shared Function GetConverterMethod(sourceType As Type, destinationType As Type) As System.Reflection.MethodInfo
      17. If sourceType Is Nothing Then Throw New ArgumentNullException("sourceType")
      18. If destinationType Is Nothing Then Throw New ArgumentNullException("destinationType")
      19. Dim srcArg As Type() = New Type() {destinationType}
      20. Dim conversionMethod As System.Reflection.MethodInfo
      21. conversionMethod = GetConversionOperatorMethod(sourceType, "op_Implicit", sourceType, destinationType)
      22. If conversionMethod Is Nothing Then
      23. conversionMethod = GetConversionOperatorMethod(sourceType, "op_Explicit", sourceType, destinationType)
      24. If conversionMethod Is Nothing Then
      25. conversionMethod = GetConversionOperatorMethod(destinationType, "op_Implicit", sourceType, destinationType)
      26. If conversionMethod Is Nothing Then
      27. conversionMethod = GetConversionOperatorMethod(destinationType, "op_Explicit", sourceType, destinationType)
      28. End If
      29. End If
      30. End If
      31. Return conversionMethod
      32. End Function
      33. Private Shared Function GetConversionOperatorMethod(type As Type, name As String, sourceType As Type, destinationType As Type) As System.Reflection.MethodInfo
      34. For Each m As MemberInfo In type.GetMember(name, MemberTypes.Method, BindingFlags.Public Or BindingFlags.Static)
      35. If TypeOf m Is MethodInfo Then
      36. Dim method As MethodInfo = DirectCast(m, MethodInfo)
      37. Dim param As ParameterInfo()
      38. If Not destinationType.IsAssignableFrom(method.ReturnType) Then Continue For
      39. param = method.GetParameters()
      40. If param.Length <> 1 Then Continue For
      41. If Not sourceType.IsAssignableFrom(param(0).ParameterType) Then Continue For
      42. Return method
      43. End If
      44. Next
      45. Return Nothing
      46. End Function

      Das ist allerdings ineffizient, sofern nicht der Delegat als erstes ermittelt und anschließend jedes mal benutzt wird.

      Gruß
      ~blaze~
      ich würde CInt nehmen, denn das ist eine annere Schreibweise des CType-Operators, also desjenigen, der inne Decimal-Struktur für diese Konvertierung vorgesehen ist.
      Convert.ToInt32() wird auch nix anneres aufrufen, aber liegt nicht inne Systematik objektorientierter Programmierung.

      Also bei CType weiß das Objekt selbst, wies konvertiert, und dassis OOP :)
      Hm, an anderen Stellen wurde ständig zur Convert-Klasse geraten... Wie man es macht, macht man es verkehrt. ;)

      Nach dem Motto: CInt() ist alt, verwende Convert.ToInt32()...

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

      Ich war eigentlich der Meinung, ich hätte diesen Umstand oben zur Genüge geklärt:

      Artentus schrieb:

      Zahl -> Zahl
      Ebenfalls ein klassischer Anwendungsfall. Entgegen der Meinung einiger Leute ist es hier vollkommen in Ordnung, CInt usw zu verwenden.

      Artentus schrieb:

      Sonderfall: Convert-Klasse
      Neben den ganzen oben genannten Konvertierungsoptionen gibt es auch noch die Convert-Klasse. Diese benötigt man im Normalfall nicht, da die Möglichkeiten von ToString, Parse usw. ausreichen.

      Artentus schrieb:

      Wenn aber kein Zwang besteht, Convert zu verwenden, weil die Funktionalität auch durch eine der oben genannten Funktionen gegeben ist, so sehe zumindest ich Convert als "weniger objektorientiert" an, ist aber streng genommen Geschmackssache.
      Decimal ist aber kein hardwarenaher primitiver Datentyp, wie du dank MathUtils ja weißt. Damit gibt's auch keine IL-Kommandos und daher ist die Frage wohl sogar berechtigt. Solange CInt wirklich zu CType und das zu einem call-Kommando ausgewertet wird, sollte es passen.
      Ich finde aber, dass man nicht unbedingt so darauf rumhacken muss und dass es eigentlich keine wirkliche Rolle spielt.

      Gruß
      ~blaze~

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

      Artentus schrieb:

      da die Möglichkeiten von ToString, Parse usw. ausreichen.

      Artentus schrieb:

      Wenn aber kein Zwang besteht, Convert zu verwenden, weil die Funktionalität auch durch eine der oben genannten Funktionen gegeben ist,


      Aber genau das war bei mir ja nicht der Fall. Parse() gibt es nur für String, deswegen dachte ich, "Kein Benutzen der Convert-Klasse" beschränkt sich darauf, dass man für String->Zahl, Zahl->String keine Convert-Klasse nutzen soll.

      Aber gut, ich nehme mein Convert aus dem Code wieder raus.
      @Artentus::
      Mir ist grade noch etwas aufgefallen, undzwar bei der Konvertierung von Boolean zu Integer. Da CInt() eine VB6-Funktion ist, und Convert.ToInt32() 'neuer', greifen sie auf unterschiedliche Konstanten zu.
      In VB6 wurde True = -1 definiert, in VB.Net mit 1.
      Sprich:

      VB.NET-Quellcode

      1. Convert.ToInt32(True) 'liefert 1
      2. CInt(True) 'liefert -1


      Sofern dies noch nicht bekannt war :thumbsup:
      »There's no need to "teach" atheism. It's the natural result of education without indoctrination.« — Ricky Gervais