22. april 2008 - 16:28Der er
11 kommentarer og 1 løsning
to dimansionelt array med int og string
Hej vil gerne lave et to dimensionelt array.. den ene domension skal indeholde en række int og den anden en række string.
Altså noget ala:
1 "dette er værdi 1" 2 "her er en string" 3 "dette er værdi nummer 3"
Findes der en måde at erklære dette eller findes der en collection class der kan afstedkomme det?
Et tillægs spørgsmål af nysgerrighed: kan man lave et array af udefinerede objekter (i Java kan man lave et array af klassen Object da denne er superklasse i Java... findes denne filosofi også i C#?)
ArrayList klassen er udefineret, men ellers kan du bruge List<Object> som så vil være en liste af elementer af typen Object, men hvorfor skal det være af typen object? Lyder lidt som en design fejl.
Hvis tallet er unikt for hver row, kan du bruge en Dictionary<int, string>:
Dictionary<int, string> myDictionary = new Dictionary<int, string>();
myDictionary.Add(1, "Dette er en værdi"); myDictionary.Add(2, "Her er en string"); osv.
Hvis du skal bruge strengen med nummer 2, skriver du:
string myString = myDictionary[2];
Ellers kan du bruge 2c's fremgangsmåde.
og ja, du kan godt bruge en object-collection til at opbevare objecter af forskellig typer. Object er superklasse til alle andre klasser, på nøjagtig samme måde som i java. Til hmortensen: Det er ikke nødvendigvis en designfejl at bruge en object-liste. F.eks. er DataSource propertien på en ListBox og en ComboBox af typen object, for ikke at lægge begrensning på hvilke typer objecter man kan vise deres liste!
Synes godt om
Slettet bruger
23. april 2008 - 10:44#4
Jeg vil ikke bruge collections med Object som løsning. Dette var blot et ekstra spørgsmål ud af min nysgerrighed. Jeg burde nok have lavet et selvstændigt spørgsmål med dette. Jeg beklager forvirringen.
Jeg anvendte en Ductionary med success så aaberg80 må gerne lave et svar for point.
"Til hmortensen: Det er ikke nødvendigvis en designfejl at bruge en object-liste. F.eks. er DataSource propertien på en ListBox og en ComboBox af typen object, for ikke at lægge begrensning på hvilke typer objecter man kan vise deres liste!"
Her er der nu altså utrolig stor forskel på om du arbejder på at lave et genneraliseret framework som alle skal kunne bruge (som dem du refererer til)... eller om du laver et specifikt projekt...
Ydermere er DataSource nok et glimrende eksempel på netop dårlig design, da den kontrakt den stiller op i form af at skulle være Object, ikke er godt nok... derimod skal det object man stiller til rådighed for DataSource overholde følgende:
"Complex DataBinding accepts as a data source either an IList or an IListSource."
Så det stinker da netop langt væk af super dårlig design.
"Her er der nu altså utrolig stor forskel på om du arbejder på at lave et genneraliseret framework som alle skal kunne bruge (som dem du refererer til)... eller om du laver et specifikt projekt..."
Helt enig!
"Ydermere er DataSource nok et glimrende eksempel på netop dårlig design, da den kontrakt den stiller op i form af at skulle være Object, ikke er godt nok... derimod skal det object man stiller til rådighed for DataSource overholde følgende:"
Den eneste måde du kan lave en property, som både kan acceptere en IList og en IListSource, er ved at deklarerer den som et object. Så den eneste mulighed Microsoft har haft for at type-binde den mere, er at lave det om til en metode med flere overloads. Dette giver dog den begrænsning, at man ikke kan tilgå DataSource listen på listboksen! Ellers må du lave flere properies til de forskellige typer datasources den kan tage imod, men så mister den lidt af sin "ease of use".
Så man har valgt at ligge et interface ind som stiller en kontrakt om 2 ting... det skal kunne returnere A. Om vi har en ListCollection tilgængelig, og B. den faktiske liste vi har tilgængelige, som sjovt nok også er en IList...
En af de virkeligt smukke ting ved combobokse og listbokse (Synes jeg :-) ), er jo netop at du kan putte næsten hvad som helst ind i dem, og det virker!
Laver du typen af DataSource propertien om til en IListSource, ville jeg nok blive lidt negativ, da de fleste af mine listbokse bruger BindingList<T> som DataSource. BindingList<T> klassen implementere ikke IListSource.
Hvis man havde lavet en metode med flere overloads, så ville du ikke kunne få fat i din datasource igen, da du mister propertiens get-metode.
Nej, heldigvis er det en smagssag, men når det gælder windows controls kan jeg godt lide at de er så generelle som mulig, så man kan bruge dem med forskellig forretningslogik. Når det gælder forretningslogikken som ligger under brugergrænsesnittet, mener jeg man bør type-begrænse det kraftigt.
"En af de virkeligt smukke ting ved combobokse og listbokse (Synes jeg :-) ), er jo netop at du kan putte næsten hvad som helst ind i dem, og det virker!"
Du kan komme en IList eller en IListSource i... thats it... (Det har intet med de underliggende objecter i de lister at gøre)
comboBox1.DataSource = new Boo(); <- Runtime Crash... comboBox1.DataSource = "Peter"; <- Runtime Crash... comboBox1.DataSource = new object(); <- Runtime Crash... comboBox1.DataSource = new Form(); <- Runtime Crash...
Okay så de er måske nok lidt trukket ud for bare at danne en pointe, ikke destomindre overholder de den kontrakt ComboBox har sat op...
Nogle ting som måske er mere sansynlige:
comboBox1.DataSource = new Dictionary<int, string>(); <- Runtime Crash... comboBox1.DataSource = new LinkedList<int>(); <- Runtime Crash... comboBox1.DataSource = new ListDictionary(); <- Runtime Crash...
Osv...
"Laver du typen af DataSource propertien om til en IListSource, ville jeg nok blive lidt negativ, da de fleste af mine listbokse bruger BindingList<T> som DataSource. BindingList<T> klassen implementere ikke IListSource."
Nej, men BindingList<T> implementere IList som er det der gør det virker... derfor ville de virke stadig... enten via:
SetDataSource(IList source); SetDataSource(IListSource source); SetDataSource(MyOwnSourceType source); <- kunne sågar implementeres via subclassing.
Eller:
comboBox1.DataSource = new ListSource<int>( new BindingList<int>() );
Og vupti. Ja som det ser ud nu, så ville det knække din kode, men det er jo kun fordi det er lavet "forkert" fra starten.
"Hvis man havde lavet en metode med flere overloads, så ville du ikke kunne få fat i din datasource igen, da du mister propertiens get-metode."
Jow man ville... jeg har aldrig sagt du skulle fjerne den property, jeg har sagt at ønsker man direkte at kunne smide en IList efter den uden først selv at pakke den ind i en IListSource, så kunne man via Metoder og overloads som demonstreret overstående tilbyde den shorthand... DataSource ville stadig eksistere, og returnere en IListSource hvorigennem din specifikke DataSource ligger.
Det du netop har beskrevet, er en workarround for at opnå type-safety. Om noget er godt eller dårligt designet, er ikke kun det samme som om det er type-safe! Andre programmeringssprog har ikke noget type-safety overhovedet, f.eks. Ruby. Prøv at sig til en Ruby programmør, at alt han nogensinde har lavet er dårligt designet, fordi det ikke er type-safe... :~S
God design har noget med, hvor nemt og hvor logisk en funktionalitet er at forstå og bruge. I langt de fleste tilfælde kan dette gøres med fuld type-safety i .NET. I nogen tilfælde kan det ikke.
Det er ikke logisk at skulle pakke en liste ind i en ListSource<T>, for at kunne sætte datasourcen. Især ikke når ListSource klassen ikke gør noget. Den må bare være der fordi... det må den bare!? Og det er slet ikke logisk, at hvis du kalder SetDataSource() med en DataTable som parameter, da kan man få fat i sin DataTable direkte igennem DataSource propertien. Men med en BindingList<T> som parameter, bliver man nød til at kalde DataSource.GetList()!
For newbe programmørere, vil dette være meget besværligt og forvirrende. Du må hele tiden vide hvilke interfaces de forskellige klasser implementerer. Når man har arbejdet med .NET i nogle år, vil det ikke være noget problem, men for en totalt nybegynder som ikke ved hvad et interface er... Ulogisk.
Keep it simple!
Jeg vil dog lige tilføje, at jeg synes det havde været rigtigt fedt, hvis microsoft havde implementeret en metode til at gøre dette type-safe. F.eks. med en attribute, hvor man kan angive tilladte typer.
Der mener jeg du anskuer ting fra en helt forkert side...
"Det du netop har beskrevet, er en workarround for at opnå type-safety. Om noget er godt eller dårligt designet, er ikke kun det samme som om det er type-safe! Andre programmeringssprog har ikke noget type-safety overhovedet, f.eks. Ruby. Prøv at sig til en Ruby programmør, at alt han nogensinde har lavet er dårligt designet, fordi det ikke er type-safe... :~S"
Der er en grund til man har valgt at lave sprog som Java or C# type safe... og det er netop fordi man vil undgå det der er sket her... Tro mig... prøv at arbejde med VB lidt og fenomenet "var"... De starter med at skyde sig selv i foden ved ikke at binde sig til en bestemt kontrakt... og så skyder det lige programmøren i foden fordi han ikke kan see hvad i alverdan han rent faktisk kan assigne...
Gode eksempler på steder hvor de har brugt object som tilladt type i deres komponenter er:
"Tag" - tag stiller ingen krav til det du putter i. Objecter i de omtalte lister her - Visning i vores ComboBox og ListBox kræver kun en ToString() metode for visning, dette lever kontrakten for Object op til, derfor ingen rumtime fejl.
"God design har noget med, hvor nemt og hvor logisk en funktionalitet er at forstå og bruge. I langt de fleste tilfælde kan dette gøres med fuld type-safety i .NET. I nogen tilfælde kan det ikke."
Hvornår var det logisk at det kun er tilladt at assigne IList og IListSource til en ting af typen Object?... Hvornår er det nemt at forstå?... Og hvordan ved man hvad man kan få retur fra den property og hvordan man anvender det?... er det nu en IList, eller er det måske en IListSource... Nej... hvis man var bundet til en kontrakt viste man hvad man havde med at gøre... Så er det bare spørgsmålet hvilken kontrakt vi skal lave...
hvis man ikke har noget fornuftigt at bruge IListSource til, så kan man jo lige så godt: public IList DataSource { get; set; }
"For newbe programmørere, vil dette være meget besværligt og forvirrende. Du må hele tiden vide hvilke interfaces de forskellige klasser implementerer. Når man har arbejdet med .NET i nogle år, vil det ikke være noget problem, men for en totalt nybegynder som ikke ved hvad et interface er... Ulogisk."
Newbe programmører forstår heller ikke hvorfor interfaces er så forbandet godt, det kræver faktisk en rum tid af erfaring for at forstå, jeg syntes da selv det var noget forbandet pjat til at starte med, i dag kan jeg finde på at lave tomme interfaces, for at garantere at man ikke kommer et new BulleBooo() i noget uden at have taget stilling til at det skal overholde en kontrakt der heder "IContract".
Men C# er jo ikke lavet til at vi kan lærer nogle at programmere, eller for at tingene skal være nemt for nybegynderne, så skulle det hvertfald aldrig nogen sinde blive brugt til kommersielle programmer.
Det er korekt at man i starten finder det ulogisk, og dumt. Men med tiden lærer man der var en super god grund, og bliver på længere sigt glad for det...
Hvad der så ville være det rigtige interface til den property, hvad det skulle garantere af funktionalitet osv, det kan så diskuteres. Så med andre ord, hvad en IDataSource helt specifikt skulle tilbyde, det ved jeg ikke og vil jeg ikke bevæge mig ind på, for det afhænger af hvordan man under neden bruger den... Men havde jeg den at gå ud fra, ville det være noget nemmere at arbejde med...
Desuden hvis vi skal definere godt design ud fra hvor nemt det er at bruge, må VB da være noget af det aller bedste... der var det da hele meget mere intuitivt for der kunne man da fint: minVar = 0 minVar += 3 minVar = new int[] minVar[0] = 5 minVar[1] = 2 minVar.Sort() minVar = "("+ minVar +")"
Det er da intuitivt!... (Men hvad er det nu lige my var er og kan undervejs?...)... Der er nok en god grund til de har droppet hele det helvede...
Synes godt om
Ny brugerNybegynder
Din løsning...
Tilladte BB-code-tags: [b]fed[/b] [i]kursiv[/i] [u]understreget[/u] Web- og emailadresser omdannes automatisk til links. Der sættes "nofollow" på alle links.