[VB.NET] Hoe object vullen zonder new object(..)

Pagina: 1
Acties:

Onderwerpen


Acties:
  • 0 Henk 'm!

  • Josvds
  • Registratie: November 2004
  • Laatst online: 26-08 20:42
Misschien een rare vraag maar hoe kan ik een object vullen zonder er een nieuw object van te declareren.

Een voorbeeld:
Ik zou bijvoorbeeld graag hebben dat iemand kan zeggen ik maakt een variabele van het type Email en vul deze door de input als een string.
Visual Basic .NET:
1
2
3
4
5
6
7
8
9
class Email
  private email As String
  property pEmail() as String
    get...    
    set...
  end property
end class

dim mijnemail As Email = "email@adres.nl"

Dus dan ik niet nogmaals een e-mail object hoef te declareren. Waarom ik dat wil, ik wil enkele standaarden aanmaken dus bijvoorbeeld Postcode, Email, etc. en dan niet de ontwikkelaars verplichten nogmaals new Email... of email.validate of email.set te gebruiken.
Gewoon enkel email = inputvalue.

Kan dat?

Acties:
  • 0 Henk 'm!

  • creator1988
  • Registratie: Januari 2007
  • Laatst online: 13:23
Ja, dit kan, maar ik heb echt geen flauw idee meer hoe dit heet.

Ah: http://msdn.microsoft.com.../z5z9kes2%28VS.71%29.aspx

[ Voor 36% gewijzigd door creator1988 op 17-05-2010 17:54 ]


Acties:
  • 0 Henk 'm!

  • Sebazzz
  • Registratie: September 2006
  • Laatst online: 19:58

Sebazzz

3dp

Ja, kan, impliciet casten moet je naar zoeken. Ik weet niet of het in VB ook kan, maar in C# kan je de cast operator overloaden. Zoeklink: http://social.msdn.micros...plicit+cast+operator&ac=8

Bijvoorbeeld:
C#:
1
2
3
4
public static implicit operator Email(string s) 
   {
        return new Email() { pEmail = s; };
   }

edit:
Nee het kan niet, je mag geen statische methode hebben die dezelfde naam als het type (in dit geval Email) heeft



De vraag is of het de juiste keuze is. Waarom niet gewoon een constructor die een string accepteert?

C#:
1
2
public Email() {}
public Email(string email) { this.Email = email; }


Waarom gebruik je trouwens hungarian notation (pEmail ipv Email)?

[ Voor 23% gewijzigd door Sebazzz op 17-05-2010 18:04 ]

[Te koop: 3D printers] [Website] Agile tools: [Return: retrospectives] [Pokertime: planning poker]


Acties:
  • 0 Henk 'm!

  • analog_
  • Registratie: Januari 2004
  • Niet online
negeer mij:

Je kan toch de property get/set het werk laten doen?
code:
1
2
3
4
Property abc {
 set { this.abc = new Abc(value) }
 get { return this.abc.abc }
}

[ Voor 4% gewijzigd door analog_ op 17-05-2010 17:58 . Reden: volledig verkeerd begrepen ]


Acties:
  • 0 Henk 'm!

  • creator1988
  • Registratie: Januari 2007
  • Laatst online: 13:23
Sebazzz schreef op maandag 17 mei 2010 @ 17:53:
Waarom gebruik je trouwens hungarian notation (pEmail ipv Email)?
En dan ook nog verkeerd... http://www.joelonsoftware.com/articles/Wrong.html

Acties:
  • 0 Henk 'm!

  • Woy
  • Registratie: April 2000
  • Niet online

Woy

Moderator Devschuur®
Impliciete conversies kun je IMHO het best zo veel mogelijk vermijden. Het werkt onduidelijke situaties in de hand.

Ik snap ook niet waarom je zo nodig op deze manier wil werken, de manier waarop je het e-mail adres meegeeft aan de constructor is IMHO veel duidelijker.

Een andere manier zou kunnen zijn om een Expliciete cast te gebruiken, dan is het tenminste duidelijk dat er een conversie plaatsvindt. Maar persoonlijk zou ik in het geval van je voorbeeld gewoon kiezen voor de methode met de constructor.
en dan niet de ontwikkelaars verplichten nogmaals new Email...
Is dat nou echt te veel moeite voor een ontwikkelaar? Door de IDE zul je het meestal niet eens zelf te hoeven typen.

Wat bij mij wel vragen oproept is waarom je voor EMail een nieuwe class definieert, als je er niet meer mee doet dan gewoon een string property toegankelijk maken.

[ Voor 26% gewijzigd door Woy op 17-05-2010 18:35 ]

“Build a man a fire, and he'll be warm for a day. Set a man on fire, and he'll be warm for the rest of his life.”


Acties:
  • 0 Henk 'm!

  • .oisyn
  • Registratie: September 2000
  • Laatst online: 19-09 21:24

.oisyn

Moderator Devschuur®

Demotivational Speaker

Josvds schreef op maandag 17 mei 2010 @ 17:41:
ik wil enkele standaarden aanmaken dus bijvoorbeeld Postcode, Email, etc. en dan niet de ontwikkelaars verplichten nogmaals new Email... of email.validate of email.set te gebruiken.
Dat lijkt me verkeerd design. Een emailadres is een emailadres (overigens geeft dat ook meteen aan dat de naam Email niet klopt - dat is namelijk het ding dat je stuurt, niet het adres waar je het naartoe stuurt). Maar een ongeldig adres is geen emailadres. Je kunt dus nooit een instantie hebben van Email waar een ongeldig adres in staat.

Een int kun je ook niet constructen uit een string. Natuurlijk, je hebt wel functionalteit om een string te converteren naar een int. Imho moet het design voor een vergelijkbaar datatype als emailadres en postcode op dezelfde manier in elkaar zitten.

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


Acties:
  • 0 Henk 'm!

  • pedorus
  • Registratie: Januari 2008
  • Niet online
Visual Basic .NET:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
    Class Email
        Private _email As String
        Property Email() As String
            Get
                Return _email
            End Get
            Set(ByVal value As String)
                'validate
                _email = value
            End Set
        End Property
        Public Shared Widening Operator CType(ByVal s As String) As Email
            Return New Email With {.Email = s}
        End Operator
    End Class

Maar eigenlijk kan dit niet kloppen, omdat niet iedere string een e-mailadres vormt, en die contructor dus een Exceptie zou kunnen gooien. Widening(vb.net)/implicit(c#) hoort hier dus niet, en het hele idee is dus fout. Waarom zou je dit willen? :p

Sowieso, waarom zou je het wiel opnieuw uitvinden? Postcode kan internationaal gezien weer heel veel waardes aannemen, en het formaat string lijkt me daar weer goed genoeg. Eventueel zou je daar ook een alias kunnen maken (Imports Postcode = System.String), maar ik zie het nut er niet direct van in.

Vitamine D tekorten in Nederland | Dodelijk coronaforum gesloten


Acties:
  • 0 Henk 'm!

  • Josvds
  • Registratie: November 2004
  • Laatst online: 26-08 20:42
Nou de reden is eigenlijk meer i.v.m. een framework dat ik aan het schrijven ben voor het bedrijf waar ik werk.
Zij maken nu een start met de .NET omgeving en komen van VBA af.

Ik wil daarbij alle functionaliteit implementeren die wij gebruiken en daaronder valt ook het ORM gedeelte.
Er zijn er zoals ik in een ander bericht had onderzocht voldoende maar geen enkele die goed past binnen onze organisatie en daarbij willen we graag meerdere functies binnen het framework samenvoegen en dat alles zelf kunnen beheren (repareren) indien er fouten aanwezig zijn, dat is bij open source toch stukken lastiger en je krijgt daarbij vele verschillende producten langs elkaar om alle problemen op te lossen.

Nou wil ik binnen het ORM voor gedefineerde velden aanmaken en niet telkens de gebruiker vereisen om bij het aanmaken van een klant het volgende te doen:
1) new klant
2) klant.email = new email(....)
of
1) new klant
2) klant.email = ....
3) (binnen de property) set new email(...)
of
1) new klant
2) klant.email = ...
3) (binnen de property) set email.set(...)

Validatie komt dan in het object e-mail zelf om te voorkomen dat er een e-mail adres wordt opgeslagen wat ongeldig is. Datzelfde geld voor alle andere objecten als bijvoorbeeld postcode, url, telefoonnummer, etc.
Bij het impliciet casten moet je een exception opgooien, maar dat moet met een construtor ook altijd. Dus de enige oplossing is dan een losse functie, want bij een SET property heb je ook geen return waarde.

[ Voor 7% gewijzigd door Josvds op 18-05-2010 08:43 ]


Acties:
  • 0 Henk 'm!

  • Sebazzz
  • Registratie: September 2006
  • Laatst online: 19:58

Sebazzz

3dp

Lijkt mij handiger om de validatie in het klant object te doen. Eventuele validatiemethodes kan je altijd nog centraliseren.
Bij het impliciet casten moet je een exception opgooien, maar dat moet met een construtor ook altijd. Dus de enige oplossing is dan een losse functie, want bij een SET property heb je ook geen return waarde.
Bij impliciet casten moet je juist geen exception opgooien. Impliciet casten mag je alleen implementeren als je weet dat het geen verwarring gaat geven, er geen data verloren gaat in het proces, en er geen exception worden opgegooid.
De andere forumleden stelden een property voor als in zo'n gebruik:
C#:
1
2
3
4
5
klant.Email = new Email();
klant.Email.EmailStr = "test@test.com";

//of kort:
klant.Email = new Email() { EmailStr = "test@test.com" };


Maar zoals al gezegd is het gewoon niet aan te raden om dit soort dingen in een aparte class op te slaan. Als je toch wil door zetten is een statische methode de enige en juiste oplossing.
C#:
1
klant.Email = Email.Parse("test@test.com");

[ Voor 78% gewijzigd door Sebazzz op 18-05-2010 08:49 ]

[Te koop: 3D printers] [Website] Agile tools: [Return: retrospectives] [Pokertime: planning poker]


Acties:
  • 0 Henk 'm!

  • Josvds
  • Registratie: November 2004
  • Laatst online: 26-08 20:42
De reden is omdat ik een standaard wil gebruiken.. Je hebt dus verschillende types binnen de variable dus bijvoorbeeld een postcode heeft een maximum lengte van 4 cijfers en 2 letters in nederland. Daar gaan we in het begin bij dit voorbeeld van uit het gaat om de maximum lengte. Daarnaast heb je bijvoorbeeld een cijfer wat een heel getal kan zijn maar ook een decimaal. Daarnaast een datum/tijd of beide en daarnaast heb je een Id wat een bepaalde lengte heeft.

Dit wordt vast gesteld in de code, vervolgens wordt bij de database conventie gekeken in welk type het daar vervolgens past. Maar dat zijn niet de enigste eigenschappen het kan bijvoorbeeld bij een nummer autonummering zijn. Ze kunnen alle standaard waardes bevatten, etc.

Dus kun je wel hanteren dat je velden een annotatie kunnen bevatten maar dan kun je ook gegevens instellen die niet van toepassing zijn om dat type veld. Dat kan verwarring veroorzaken, daarnaast mis je dan automatische validatie, etc.

Als dus alle input altijd gedaan kan worden door rechtstreeks bij een email veld een string input te valideren, een postcode string input te valideren, een telefoonnummer te valideren, een datum af te splitsen van datetime, etc.. En dat alles kan dan doormiddel van:

Visual Basic .NET:
1
2
3
4
5
6
7
dim mijnemail as Email = "mijn@mail.nl"
dim mijnpostcode as Postcode = "1234AB"
dim mijntelefoon as Telefoon = "0123456789"
dim mijngebdatum as Datum = DateTime.Now
dim mijngebtijd as Tijd = DateTime.Tijd
dim mijnnummer as Nummer = 1234
dim mijnbedrag as Bedrag = 12.34


Ik wil namelijk niet bij klant, gebruiker, medewerker, familie, credituer, debiteur, stagaire, bedrijf, etc. allemaal zelf de validatie functie van een e-mail adres aanroepen. Dit kan fouten veroorzaken dat er alsnog gegevens in kunnen die niet correct zijn.

Het voordeel van het Email object is dat je ook gelijk de functionaliteit kunt inbouwen m.b.t. het uitlezen van bijvoorbeeld het domein, landcode, etc.

[ Voor 11% gewijzigd door Josvds op 18-05-2010 09:14 ]


Acties:
  • 0 Henk 'm!

  • Woy
  • Registratie: April 2000
  • Niet online

Woy

Moderator Devschuur®
Maar ik zie nog steeds het probleem niet met het gewoon aanroepen van de constructor? Hoeveel moeite is dat nou. Je krijgt er wel een hoop duidelijkheid voor terug. Juist het gebruik van dit soort impliciete casts is erg foutgevoelig.

Desnoods maak je bij een Customer/ander object een constructor die wel strings accepteerd, maar het in de constructor zelf omzet naar het juiste type.
C#:
1
2
3
4
5
6
7
8
9
10
11
class Customer
{
    public Customer( string emailAddress )
    {
         EmailAddress = new EmailAddress( emailAddress );
    }

    ....
}

Customer cust = new Customer( "blaat@blaat.com" );

Al zou ik dan altijd ook een overload bieden die wel gewoon een EmailAddress accepteerd, anders kom je weer in de knoop als je ergens toch een EmailAddress vandaan krijgt i.p.v. een string.

[ Voor 74% gewijzigd door Woy op 18-05-2010 09:29 ]

“Build a man a fire, and he'll be warm for a day. Set a man on fire, and he'll be warm for the rest of his life.”


Acties:
  • 0 Henk 'm!

  • Josvds
  • Registratie: November 2004
  • Laatst online: 26-08 20:42
Woy schreef op dinsdag 18 mei 2010 @ 09:24:
Maar ik zie nog steeds het probleem niet met het gewoon aanroepen van de constructor? Hoeveel moeite is dat nou. Je krijgt er wel een hoop duidelijkheid voor terug. Juist het gebruik van dit soort impliciete casts is erg foutgevoelig.

Desnoods maak je bij een Customer/ander object een constructor die wel strings accepteerd, maar het in de constructor zelf omzet naar het juiste type.
C#:
1
2
...
Customer cust = new Customer( "blaat@blaat.com" );
Daar heb je gelijk in trouwens ja, als je alles op deze manier vult is dat hetzelfde als dat je alles zonder contructor vult en bij een constructor kun je meerdere dingen meegeven. Maar even voor mezelf want ik snap niet heel goed wat het impliciet casten zoveel slechter maakt vergeleken met de constructor, je geeft aan welk type gecast kan worden naar email. Dat doe je bij de contructor ook je geeft een string mee. Bij beide geeft je een exeption indien het fout gaat.

Acties:
  • 0 Henk 'm!

  • Woy
  • Registratie: April 2000
  • Niet online

Woy

Moderator Devschuur®
Impliciete cast zijn er voor conversies die niet fout horen te gaan, en waar het ook logisch is dat ze geconvert worden.

Zoals bij bijvoorbeeld een byte -> int als je een vermenigvuldiging doet van byte * int. Dat is ook de reden dat het een widening operator is. Het type word groter gemaakt.

Zie het als de inhoud van een 1 liter vat overgieten in een 10 liter vat. Dat gaat altijd goed, maar de inhoud van een 10 liter vat overgieten in een 1 liter vat (narrowing) wil je alleen doen als je zeker weet dat er geen overflow optreed. Dat is de reden dat je het expliciet aan wil geven.

“Build a man a fire, and he'll be warm for a day. Set a man on fire, and he'll be warm for the rest of his life.”


Acties:
  • 0 Henk 'm!

  • creator1988
  • Registratie: Januari 2007
  • Laatst online: 13:23
Punt hier is, dat je dingen over bepaalde velden in je entity wil gaan zeggen. Dit moet je echter niet doen door middel van het type, want een postcode is nou eenmaal een string.

Visual Basic .NET:
1
2
3
4
5
6
7
8
9
Private _postcode As String
 Public Property Postcode() As String
     Get
         Return _postcode
     End Get
     Set(ByVal value As String)
         _postcode = value
     End Set
End Property


Wat zeg je hier? Ik heb een postcode. Klaar. Het is een string, maar ik ga geen eisen stellen aan het formaat op dit moment.

Waarom wil je dit? Omdat het type 'postcode' niet veel zegt, is het een Nederlandse postcode, of een Franse, of een? Je validatielogica is van veel meer factoren afhankelijk. Daarom wil je pas valideren als je hele object compleet is, omdat je dan op basis van meerdere properties beslissingen kan nemen.

Bijvoorbeeld:

Visual Basic .NET:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
Public Structure Country
Private _PostcodeFormat As Regex
    Public Property PostcodeFormat() As Regex
        Get
            Return _PostcodeFormat
        End Get
        Set(ByVal value As Regex)
            _PostcodeFormat = value
        End Set
    End Property
End Structure

Public Interface IValidate
    Function Validate() As ValidationMessage
End Interface

Public Class Klant
    Implements IValidate
Private _Postcode As String
    Public Property Postcode() As String
        Get
            Return _Postcode
        End Get
        Set(ByVal value As String)
            _Postcode = value
        End Set
    End Property
Private _Land As Country
    Public Property Land() As Country
        Get
            Return _Land
        End Get
        Set(ByVal value As Country)
            _Land = value
        End Set
    End Property
    
    Public Function Validate() As ValidationMessage
        Dim valMsg = New ValidationMessage()
        
        If Not Land.PostcodeFormat.Match(Postcode).Success Then
            valMsg.Add("Postcode is in ongeldig formaat")
        End If
        
        Return valMsg
    End Function
End Class


Je kunt nu gerust je object vullen met bogus data, en vervolgens je object valideren. Pas dán kan je er iets zinnigs over zeggen.

Acties:
  • 0 Henk 'm!

  • Josvds
  • Registratie: November 2004
  • Laatst online: 26-08 20:42
Woy schreef op dinsdag 18 mei 2010 @ 10:16:
Impliciete cast zijn er voor conversies die niet fout horen te gaan, en waar het ook logisch is dat ze geconvert worden.

Zoals bij bijvoorbeeld een byte -> int als je een vermenigvuldiging doet van byte * int. Dat is ook de reden dat het een widening operator is. Het type word groter gemaakt.

Zie het als de inhoud van een 1 liter vat overgieten in een 10 liter vat. Dat gaat altijd goed, maar de inhoud van een 10 liter vat overgieten in een 1 liter vat (narrowing) wil je alleen doen als je zeker weet dat er geen overflow optreed. Dat is de reden dat je het expliciet aan wil geven.
Maar als je het doet als hieronder dan maak je toch ook gebruik van de constructor methode? Ik begrijp het verschil niet echt tussen rechtstreeks de constructor aanroepen en het uitvoeren d.m.v. de operator, want je geeft aan dat bij beide de input een string is, dus getallen kunnen er zoiezo ook bij de constructor in.. Hetzelfde geld dus als je een integer in een bit probeert te stoppen. Dan zou je dus bij een constructor een bit defineren als input maar ook bij de ctype. Zoals ik het zie kan je met de operator dezelfde fouten maken als met de constructor, of zie ik dat verkeerd?

Visual Basic .NET:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
Public Class Email

    ' Converter
    Public Shared Widening Operator CType(ByVal iValue As String) As Email
        Return New Email(iValue)
    End Operator



    ' Variable
    Private _email As String

    ' Constructor
    Public Sub New(ByVal iValue As String)
        Me._email = iValue
    End Sub

    ' Property
    Public Property email() As String
        Get
            Return _email
        End Get
        Set(ByVal value As String)
            _email = value
        End Set
    End Property

End Class

Acties:
  • 0 Henk 'm!

  • Woy
  • Registratie: April 2000
  • Niet online

Woy

Moderator Devschuur®
Josvds schreef op dinsdag 18 mei 2010 @ 10:30:
[...]
Ik begrijp het verschil niet echt tussen rechtstreeks de constructor aanroepen en het uitvoeren d.m.v. de operator, want je geeft aan dat bij beide de input een string is, dus getallen kunnen er zoiezo ook bij de constructor in.
Het verschil is dat je het bij de ene expliciet doet, en dus moet nadenken over de consequenties, en dat het bij de andere impliciet gebeurt. Als je een expliciete cast uitvoert dan geef je aan dat je nagedacht hebt over de consequenties, en er dus of zeker van bent dat de conversie altijd goed gaat, of dat je zorgt dat een eventuele fout bij de conversie afgevangen word.

“Build a man a fire, and he'll be warm for a day. Set a man on fire, and he'll be warm for the rest of his life.”


Acties:
  • 0 Henk 'm!

  • CyBeRiZzY
  • Registratie: Maart 2003
  • Laatst online: 22-03-2022
Volgens mij gewoon de property als default in te stellen

Acties:
  • 0 Henk 'm!

  • pedorus
  • Registratie: Januari 2008
  • Niet online
CyBeRiZzY schreef op woensdag 09 juni 2010 @ 20:10:
Volgens mij gewoon de property als default in te stellen
VB6 ligt toch al een tijdje achter ons.. ;)

Vitamine D tekorten in Nederland | Dodelijk coronaforum gesloten

Pagina: 1