torsdag den 17. januar 2013

Hvordan object initializers virker i ASP.NET 3.5

Jeg sad i dag og rodede med noget .NET kode, og fik mig så lidt en slem overraskelse med object initializers.
Det er en mega mega lækker ting som gør det meget nemmere for dig at danne dine objekter, da du ikke behøver at lave en constructor der tager alle dine parametre med.
Det jeg snakker om er fx:
public Course AddCourse(DateTime startDate, DateTime endDate, string title, string lokationAfholdt, string By, string beskrivelse, Employment underEmployment)
        {
            Course kursus = new Course() { StartDate = startDate, EndDate = endDate, Name = title, TypeOfExperience = ExperienceType.Kursus, isCompanyExperience = false, Location = new Location(lokationAfholdt, "(ingen adresse)", 9999, By, "(ingen landekode)"), DuringEmployment = underEmployment };
}

Jeg har altid troet at fordi du sætter alle dine properties herinde, så sættes disse før din constructor kaldes. Så du kan sætte værdier selv og så få din constructor til at reagere på dem.

Det viste sig så at det er modsat. Altså først kaldes .NET constructoren, dernæst sættes dine properties.
Så du skal ikke lave metoder i din constructor der er afhængig af satte metoder.
Jeg havde fx. en periode beregning imellem start og slut date, men desværre så blev den beregnet forkert fordi de properties den skulle lave beregningen efter var desværre ikke sat men blev sat bagefter.
Så jeg skulle enten lave en constructor med input som lavede beregningen, eller kalde beregningen selv hver gang efter jeg havde lavet objektet.

Så du skal tænke over hvordan du laver dine objekter og mønstre for ellers kan det blive en dårligere løsning end du havde planlagt.

Jeg har altid troet at fordi det hed CONSTRUCTOR (inline-constructor) så lavede .NET automatisk en constructor for dig til det, så det blev i constructoren at du ville have dine værdier sat.
I dag fandt jeg ud af det faktisk ikke er nogen constructor, men property-sætter. Også kaldet object initializers.
For det der rent faktuelt sker er at den laver objektet (fx. Course) med din constructor, og bagefter kalder den dine properties og sætter dem til disse værdier.
Så hvis du i constructoren er afhængig af disse variabler, skal du tage hensyn til det og gennemtænke dit design.
Jeg har selv lige fået en fejl der bevirkede at en periode beregning blev til dags dato i periode, så alle kurser jeg havde sat ind med start og slut dato blev nu beregnet som år 0 til i dag.
Det er en lille bitte smule farligt hvis man ikke lige er klar over det - hvilket jeg faktisk ikke var.

Men dog alligevel sad jeg for et par dage siden og snakkede med en fælles kollega udvikler, som var irriteret over at han skulle lave et objekt og så sætte properties - eller skulle lave en constructor for at kunne sætte en property. Dette er fordi vi arbejder i .NET 2.0 (som skal opgraderes til .NET 3.5 - .NET 4.0) så kunne kun berolige ham om det ville blive MEGET MEGET bedre! Netop fordi du får object initializers hvor du kan sætte det hele, men så affyres din constructor bare ikke længere som du måske vil forvente. Tænkte ikke videre over at du nok erstatter din C# constructors måde at blive kaldt på, så den afvikles som man måske ikke lige forventer.

2 kommentarer:

  1. Hej Laurits. Den tekniske term er faktisk "object initializers".

    "Tænkte ikke videre over at du nok erstatter din C# constructor, med din inline-constructor og derfor afvikles den ikke."

    Din ctor erstattes ikke. Du sætter blot dine properties efter din ctor - som du vist også skriver længere oppe. Men rart at se nogen blogge om udvikling i MS miljø :-)

    SvarSlet
    Svar
    1. Hej

      Hvis det er tilfældet så har jeg nok haft dummet mig med ikke at lave min kode i en parameterløs constructor for jeg havde noget kode der skulle hjælpe mig når jeg lavede et Course. Det var fordi den skulle selv undersøge en masse i constructoren, men dette kode blev desværre aldrig afviklet.

      Har lige afprøvet det og kan godt se det virker som det skal, hvilket var det jeg havde forventet også. Enten har min constructor ikke været parameterløs, eller også har det jeg skulle tjekke for ikke været sat endnu. For jeg troede faktisk at det jeg ville sætte i initialization ville være sat inden constructoren, så jeg kunne sætte ting og så få afviklet min logik. Det viste sig desværre ikke at være sådan, men at den bliver lavet før og derfor ikke passede ind i min struktur.

      Slet

Kan du lide mit indlæg, har en kommentar, forslag eller andet på hjerte så skriv venligst