none
Eigene Werttypen deklarieren RRS feed

  • Frage

  • Hallo, ich verwende Visual Studio 2010 und habe 2 Fragen

    a) kann man einen eigenen Wert-Typen deklarieren ? z.B. names integertyp namens KundenNr.  Mir geht es dabei hauptsächlich dabei um die Übersichtlichkeit, damit z.B bei einer Funktionsdeklaration dann der Übergabeparameter nicht int sonder KundenNR ist.

    b) kann man einen Typ als Ersatz für  -> As Dictionary(Of Integer, IrgendeinObjecttyp) definieren? Dabei gehts mir darum, Schreibarbeit zu sparen.

    vielen Dank

       
    Montag, 16. Juli 2012 15:24

Antworten

Alle Antworten

  • Hi,

    zu a) Kann man schon, die Frage ist, ob man das will. Direkt von Int32 oder ähnlichem ableiten kannst Du nicht, wenn man sich die Structure zu Int64 mal mit dem .NET Reflector anschaut, weiß man auch, dass man das eher nicht machen will, nur um die Übersichtlichkeit zu erhöhen (allerdings führt deine Überlegung in meinen Augen eher genau zum Gegenteil).

      http://msdn.microsoft.com/de-de/library/ms173104.aspx#mt63

    Evtl. reicht dir ja aber auch ein Aliasname für Int32 ...

      http://www.codeproject.com/Articles/30566/Using-Data-Type-Alias-in-Net

    Zu b) Welche Schreibarbeit? Was genau willst Du hinterher mit dem Ersatz machen? Poste bitte mal ein exaktes Beispiel dessen, was Du mit einem Dictionary wie dargestellt machen würdest und wo dich dann bei der Verwendung desselben der Schreibaufwand stört.


    Gruß, Stefan
    Microsoft MVP - Visual Developer ASP/ASP.NET
    http://www.asp-solutions.de/ - Consulting, Development
    http://www.aspnetzone.de/ - ASP.NET Zone, die ASP.NET Community


    Montag, 16. Juli 2012 15:44
    Moderator
  • Hallo,

    zu a)
    Das geht in der Form nicht.
    Die Typen kann man nicht redefinieren, da es zum einen der Typsicherheit widersprechen würde (KundennNr wäre ein eigener Typ)
    zum anderen erfahren integrierte Typen (wie Integer / Int32) einige Sonderbehandlungen seitens der Laufzeit.

    Du könntest zwar eine Structure (Werttyp) definieren, wirst Du dort mindestens eine Feld / Eigenschaft (hier mit Integer)
    implementieren müssen - wirklichen Mehrnutzen hast Du damit alleine nicht.
    Und wenn Du mit strikter Überprüfung arbeitest, werden Zuweisungen imkompatibler Typen eh bereits erkannt.

    zu b)
    Wenn Du einen generischen Typ mit spezifischen Parameter immer wieder benutzt, so kannst Du eine Ableitung erstellen, z. B.:

    Public Class MyDictionary
        Inherits System.Collections.Generic.Dictionary(Of Integer, String)
    End Class

    Hier gilt wieder das oben Gesagte: Es handelt sich um einen neuen (eigenen) Typ.
    Und schnell schlagen solche Dinge wie Ko-/Kontravarianz zu,
    siehe Kovarianz und Kontravarianz in Generika
    und Kovarianz und Kontravarianz (C# und Visual Basic)
    Wenn man sich damit nicht gut auskennt und der Konsequenzen klar ist, sollte man das deswegen meiden.

    In den meisten Fällen reicht es den Typrückschluss von Visual zu nutzen, um nicht mehr als notwendig zu tippen:

        Public Sub UseDictionary()
            Dim dict = GetDictionary()
        End Sub
    
        Public Function GetDictionary() As Dictionary(Of Integer, String)
            Dim dict As New Dictionary(Of Integer, String)
            Return dict
        End Function
    

    Und am Ende gilt: Visual Basic ist nunmal etwas geschwätziger als andere Sprachen (z. B. C#)...

    Gruß Elmar

    Montag, 16. Juli 2012 15:58
    Beantworter
  • @Stefan Falz:

    Danke, die alias-Methode sieht Vielversprechend aus. Werde mal testen.

    Die Schreibarbeit entstand z.B, wenn man ein Grid mit 8 Spalten hat und zum Sortieren 8 Icomparer erstellen mußte, bei denen zwei Objekte verglichen wurden.

    @Elmar Boyle:

    Generische Typen einzusetzen ist wahrlich mit Kanonen auf Spatzen zu schießen.

    Gibt es nicht sowas wie #Include, sprich ein Möglichkeit, im Editor statt immer

     Public Function Compare(ByVal x As System.Collections.Generic.KeyValuePair(Of Double, Integer), ByVal y As System.Collections.Generic.KeyValuePair(Of Double, Integer)) As Integer Implements System.Collections.Generic.IComparer(Of System.Collections.Generic.KeyValuePair(Of Double, Integer)).Compare
       

    zu schreiben, z.B.

    ByVal x as %Typ1%
    ?


    Montag, 16. Juli 2012 16:10
  • Hallo,

    wozu braucht man acht Comparer -vorausgesetzt man jongliert nicht mit acht eigenen Klassen?

    Gruß Elmar

    Montag, 16. Juli 2012 16:22
    Beantworter
  • Hallo,

    wozu braucht man acht Comparer -vorausgesetzt man jongliert nicht mit acht eigenen Klassen?

    Gruß Elmar



    weil für jede Spalte besodere/eigene Sortierregeln gelten. ( Dieser GAU trat jedoch nicht ein. Tatsächlich summieren sich die Comparer durch viele verschiedene Tabellen)
    Montag, 16. Juli 2012 16:32
  • Tja, wenn man ein miserables Design hat, hast man schon sein Kreuz zu tragen...

    Montag, 16. Juli 2012 17:13
    Beantworter
  • Hallo Algernoon,

    zum ersten Punkt. Man könnte eine eigene Kundennummer Klasse erstellen. Diese kann dann auch gleich den Validierungscode enthalten. Das frühere Default Property von VB6 hätte sich dazu geeignet. Das verlangte noch keine Parameter. Ohne Default Property z.B.


    Public Class Kundennummer
      ' Value ist die Kundennumer.
      Private mintValue As Integer

      Public Property Value() As Integer
        Get
          Return mintValue
        End Get

        Set(ByVal value As Integer)
          Kundennummer_Validate(value)

          ' Value erst nach Validierung setzen.
          mintValue = value
        End Set
      End Property

      Private Sub Kundennummer_Validate(ByVal value As Integer)
        ' Code zum Prüfen ob Kundennummer gültige Form hat.
        If value < 100000 Or value > 999999 Then
          Throw New ArgumentException("Die Kundennummer muss 6 stellig sein.")
        End If
      End Sub


      Public Sub New(ByVal pintValue As Integer)
        mintValue = pintValue
      End Sub
    End Class


    Public Class Form1
      Private Sub Form1_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
        Try
          Dim Kundennummer As New Kundennummer(222222)

          ' Bei Zugriff auf die Kundennummer selbst muss dann halt Value angegeben werden.
          MsgBox(Kundennummer.Value)

          Kundennummer.Value = 444444
          ZeigeKundennummer(Kundennummer)

          ' Ungültige Kundennummer.
          Kundennummer.Value = 1

        Catch ex As Exception
          MsgBox(ex.Message)
        End Try
      End Sub


      Private Sub ZeigeKundennummer(ByVal Kundennummer As Kundennummer)
        MsgBox(Kundennummer.Value)
      End Sub
    End Class

    • Bearbeitet Markus222 Montag, 16. Juli 2012 22:34
    Montag, 16. Juli 2012 22:11
  • Falls es vorkommen sollte dass eine Klasse die ein Property vom Typ Kundennumer hat dieses direkt als Integer Wert ohne Aufruf von Value zurückgeben muss müsste man dann ein zusätzliches Integer Property deklarieren.


    Public Class Test
      Public Kundennummer As New Kundennummer

      Public Property Kundennummer_Int As Integer
        Get
          Return Kundennummer.Value
        End Get

        Set(ByVal value As Integer)
          Kundennummer.Value = value
        End Set
      End Property
    End Class


    Public Class Form1
      Private Sub Form1_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
        Try
          Dim objTest As New Test

          objTest.Kundennummer.Value = 111111

          objTest.Kundennummer_Int = 222222

          MsgBox(objTest.Kundennummer.Value)

        Catch ex As Exception
          MsgBox(ex.Message)
        End Try
      End Sub
    End Class

    Montag, 16. Juli 2012 23:04
  • Tja, wenn man ein miserables Design hat, hast man schon sein Kreuz zu tragen...

    @Elmar Boyle:  ich hab zwar ein miserables design, die vielen Comparer sind aber nicht zu umgehen, da die Anwedung halt etwas komplexer ist.

    Mittwoch, 18. Juli 2012 18:59
  • @Markus SchertlerDie Lösung mit Klassen verwende ich zwar auch, aber für einfache Wertvariable ohne validierungsbedarf soviel Zeilen Code zu schreiben macht es IMHO  nicht gerade übersichtlicher. Die Alias-Lösung ist da wohl passender.Ziel ist einfach nur, den Quelltext möglichst selbsterklärend zu machen,. da mein Gedächtnis nicht das beste ist.

    Mittwoch, 18. Juli 2012 19:12
  • Gerade, weil das Gedächtnis nicht immer das Beste ist, erleichtert die Kapselung in Klassen den Überblick enorm.
     
    --
    Viele Gruesse
    Peter
    Donnerstag, 19. Juli 2012 06:43
  • Wohl wahr. Mann kanns aber auch übertreiben.
    Freitag, 20. Juli 2012 08:10
  • Übertreiben ist, wenn wegen fehlender Kapselung der Überblick verloren geht. Etwas mehr Aufwand bei der Projektierung (incl. Konzeptionierung) bringt enorme Einsparungen in den späteren Phasen des Software-Lebenszyklus (insbesondere bei der Fehlerbeseitigung und bei nachträglich erforderlichen Anpassungen).
     
    --
    Viele Gruesse
    Peter
    Freitag, 20. Juli 2012 08:33
  • Übertreiben ist, wenn der Überblick verloren geht.  Das hat viele Gründe. Alles nur auf fehlende Kapselung zu reduzieren ist etwas blauäugig. In der Therie ist das alles so toll, aber ich habe leider noch nie diese Phasen des Software-Lebenszyklus im praktischen Leben so umgestzt gesehen. Die "Lastenhefte" meines Arbeitgebers waren weder vollständig noch logisch konsistent. Aber da bin ich sicher eine Ausnahme.

    Freitag, 20. Juli 2012 11:01
  • Außer der Kapselung in Namensräume, Klassen und Methoden fallen wir keine weiteren programmtechnischen Mittel ein, den Überblick zu verbessern.
     
    Meine Erfahrung ist, dass eine falsche oder unzureichende Kapselung bei der Fehlersuche oder bei späteren Erweiterungen nur zusätzlichen Aufwand bedingt. Ein Lastenheft hat nicht die Aufgabe,  Vorgaben zur Strukturierung (incl. Kapselung) eines Projektes zu machen. Das obliegt dem “Software-Designer”.
     
    --
    Viele Gruesse
    Peter
    Freitag, 20. Juli 2012 11:32
  • Die beiden wichtigsten Methoden sind meiner Meinung nach:

    Programm dokumentieren (hier schlampt auch z.B. die Onlinehilfe von Microsoft)

    Quelltexte kommentieren (dito)

    Und ein Programm zu strukturieren, das dam am Ende ganz anders aussieht, wie ursprünglich gesagt, fällt mir immer noch schwer.


    Freitag, 20. Juli 2012 12:26
  • Es ist oft mühsam Dokumentation und Kommentare bei Änderungen auf den neuesten Stand zu bringen. So dass es mit der Zeit auseinanderläuft.

    Daher ist meiner Meinung nach das wichtigste das Vermeiden von Redundanz. Und damit einer Fehlerquelle. Für alles also ein einziger Platz.

    Das ist zuerst mühsamer als Codestellen einfach zu kopieren. Doch es erleichtert die Wartbarkeit des Programms und auch die Lesbarkeit. Um Redundanz zu vermeiden sind wohl die Dinge Peter nannte Mittel der Wahl.

     

     

    Freitag, 20. Juli 2012 13:23
  • Redundanzvermeidung gehört bei mir auch zu den Top-Kandidaten. Aber nur weil Kommentieren mühsam ist, ist es immer noch nicht unwichtig!

    Freitag, 20. Juli 2012 13:45
  • Hi Algernoon,

    Kommentare gehören zu den so genannten Smells in der Programmierung.

    Meistens ist der Kommentar überflüssig.

    'Setze Kunden Vorname
    Kunde.Vorname = vorname

    Oder es Passiert etwas komplexes.

    Dann sollte die Sache besser in ein Methode ausgelagert werden. Die dann einen Sinnvollen Namen bekommt.

    MFG

    Björn

    Freitag, 20. Juli 2012 17:57