webForumDet fria alternativet

.NET C# i största allmänhet?

.NETur .NET

7 svar · 703 visningar · startad av CatZ

Medlem sedan jan. 20022 440 inlägg
Frågan#1

Jag satt och klurade lite på ett par saker. Kommer bara på den ena nu så jag tar nästa när jag kommer på det.

Det finns ju flera olika sätt att göra saker på om jag vill typkonvertera från något en DropDownList.SelectedValue kan jag göra på olika sätt.

1. (int)DropDownList.SelectedValue;
2. Convert.ToInt32(DropDownList.SelectedValue);
3. Int32.Parse(DropDownList.SelectedValue);
4. DropDownList.SelectedValue as int;

Vad är skillnaden? Jag skulle iofs kunna kolla upp allihop var för sig säkerligen klura ut det själv men jag antar att många här kan svara på den frågan på ett bättre sätt.

Medlem sedan dec. 19996 721 inlägg
#2

Till att börja med..

1. (int)DropDownList.SelectedValue;
4. DropDownList.SelectedValue as int;

är typomvandlingar, medan

2. Convert.ToInt32(DropDownList.SelectedValue);
3. Int32.Parse(DropDownList.SelectedValue);

är konverteringar. Terminologin är inte solklar, men skillnaden är stor. En typomvandling (cast) kan endast göras till en variabels faktiska datatyp, eller uppåt i dess arvshierarki. Man kan inte casta en sträng till en int, men däremot till object. Man kan casta object till string, förutsatt att den egentliga datatypen är string. Det går att ändra detta beteende, men sådan är grunden.

Konverteringarna däremot är kompletta metoder som gör sitt bästa för att tolka värdet i en datatyp och konvertera det till en annan.

Convert.ToInt32 anropar faktiskt Int32.Parse, med den skilladen att 0 returneras om strängen är null.

Varken "(int)DropDownList.SelectedValue" eller
"DropDownList.SelectedValue as int" är tillåtna, dels för att man inte kan casta string till int, dels för att "as" inte är tillåtet med annat än referenstyper. Skillnaden mellan "(typ)" och "as typ" är dock att "as typ" returnerar null om typomvandlingen inte kunde genomföras, medan "(typ)" ger en exception. Det finns underliggande skillander i vilken IL-kod som genereras också, men det är av mindre betydelse.

Medlem sedan jan. 20022 440 inlägg
#3

Nej jag vet att de (int) och as int inte är tillåtna i det fallet var mest för diskussionens skull.

Anser definitivt att jag fick svar på den frågan. Så jag ska snart skriva nästa :)

Medlem sedan jan. 20022 440 inlägg
#4
  1. Är det vettigt att använda sig av transactions för att behålla konsistens på datan i databasen eller ska man försöka programmera runt alla problem som kan dyka upp?

  2. Jag vet vad det är för skillnad på protected, private och public på en class men har inte förstått vad jag ska använda det till egentligen.... Antar att det är för att jag inte är så noga när jag deklarerar mina variabler. Hur ska man göra här egentligen?

    Det jag tänker på är att jag säkert borde bli lite bättre på hur jag deklarerar mina variabler i funktionerna. Ska man deklarera sånt som inte används utanför funktionen som private eller ska jag inte bry mig så mycket om det där?

Medlem sedan maj 20012 812 inlägg
#5

Catz skrev:

Är det vettigt att använda sig av transactions för att behålla konsistens på datan i databasen eller ska man försöka programmera runt alla problem som kan dyka upp?

Transaction skall du använda dig av när du vill att ALLT eller INGET skall genomföras. Alltså om du skall göra fem INSERT statement mot din databas eller 5 olika databaser för den delen, och så vill du vara säker på att ALLA 5 skall sättas in eller ingen. Det är inget som du försöka programmera runt på egen hand, utan använda de funktioner som finns. Visst kan du lösa det på egen hand, men jag skulle definitivt inte råda det till dig, det kan lätt bli väldigt komplicerat.

Catz skrev:

Jag vet vad det är för skillnad på protected, private och public på en class men har inte förstått vad jag ska använda det till egentligen.... Antar att det är för att jag inte är så noga när jag deklarerar mina variabler. Hur ska man göra här egentligen

Det är ganska självbeskrivande, tja kanske inte protected eller Internal. Men Private är som den beskriver privat för min egen klass. Det betyder att det är endast inne ifrån klassen som man kan komma åt denna metod, vilket är väldigt behändigt när du delar upp någon sorts logik i flera metoder för att återanvända dem, eller för att underlätta kodförståelsen. Det är ju inget som du vill att användaren av din klass skall se. För att ta ett exempel, så tar vi bilklassen.

På denna klass har du en metod (publik) GörOmKörning() som kan anropas för alla som har en instans av din klass (alltså de har en bil). Men när du menar GörOmKörning() så menar du egentligen:

1. TittaBakåt();
2. TittaDödaVinklen();
3. SättPåBlinkers();
4. BytFil();
5. GasaSomFan();
6. KontrolleraSåDuPasseratBilen();
7. TittaDödaVinklen();
8. BytFil();
9. StängAvBlinkers();

osv osv... Detta (och säkert mer) skall göras när du skall göra en omkörning, men du vill ju inte att föraren skall behöva vet allt detta, utan han skall bara behöva bestämma att det är dags för en omkörning och sedan fixar din omkörningsmetod allt det andra "under skalet". Det är så du använder private/public. Public till allt som du vill exponera från din klass, och private för allt som du inte vill att någon annan skall känna till.

Protected fungerar som ett mellanting mellan public och private så till vida att den är private för att som har en instans av ditt objekt, men public för alla klasser som ärver från ditt objekt.

Så i vårt bil förhållande så hade vi gjort så att istället för att ha alla de 9 metoderna private så kan vi sätta dem till protected, du kan man fortfarande inte se dem om du har en instans av klassen bil, du ser fortfarande bara GörOmKörnings() metoden. Men om vi nu skapar en SportBil{} klass och ärver från vår Bil{} klass, så fungerar dessa 0 metoder nu som privata metoder i bilen SportBil{} och vi kan göra en ny GörOmKörningsSportBil() metod (eller ännu bättre använa override och virtual på de olika metoderna, mer om det senare) och i denna metod, så struntar vi att använd blinkers och vi får då en "snabbare" omkörning ;)

Internal fungera så att den är public i samma assembly, men privat för alla utan för assemblyn. Alltså en klass som är Internal i en assembly kan bara anropas från klasser i detta assemblyt och inte från klasser i ett annat assembly.

Nu kommer det roliga. Abstracta och Virtuella metoder, här kan man nu börja se fördelarna med oo-programmering, då vi kan få 2 helt olika flöden på "samma metod" i olika klasser.

Säg att vi skapar klassen bil, och gör en metod som heter GörOmKörning() men vi gör den virtuell.

public Virtual bool GörOmKörning()
{
    TittaBakåt();
    TittaDödaVinklen();
    SättPåBlinkers();
    BytFil();
    GasaSomFan();
    KontrolleraSåDuPasseratBilen();
    TittaDödaVinklen();
    BytFil();
    StängAvBlinkers();
}

Vad vi nu har har sagt här är att denna klass har en metod som heter GörOmKörning() men klasser som ärver från denna klass får lov överrida denna metod med sin egen kod.

Så i klassen SportBil{} som kan vi ha en liknande metod.

public class SportBil : Bil{
 public override bool GörOmKörning()
 {
    TittaBakåt();
    TittaDödaVinklen();
    BytFil();
    GasaSomFan();
    KontrolleraSåDuPasseratBilen();
    TittaDödaVinklen();
    BytFil();
   }
}

Här har vi nu 2 olika metoder men med samma namn, och varför är det så himla bra då? Kunde vi inte bara döpt den till GörOmKöring2() och så anropt den metoden istället. Ja visst kunde du ha gjort det, men med denna lösning så behöver du faktiskt inte vet vilken typ du bil är, säg att du har en lista som tar typen bil

List<Bil> bilList = new List<Bil>();

Denna lista kan nu innehålla både bil och SportBil.

bilList.Add(new Bil());
bilList.Add(new SportBil() as Bil);

om jag nu då vill göra en omkörning på alla mina bilar i listan så skulle man ju kunna göra så här:

foreach(Bil bil in bilList)
{
   if(bil.GetType() == typeOf(SportBil))
      ((SportBil)bil).GörOmKörning2();
   if(bil.GetTYpe() == typeOf(Bil))
      bil.GörOmKörning();
}

Men hur snyggt är det och framför allt hur praktiskt är det, det kan ju faktiskt komma någon som skapar en LastBil som ärver från din Bil och lägger med den i listan, då kommer den aldrig att göra någon omkörning eftersom det alternativet inte finns med.

Men om vi istället har löst det så som vi har gjort med Virtual och override, så löser vi det så här.

foreach(Bil bil in bilList)
   bil.GörOmKörning();

Och korrekt metod kommer att anropas för respektive typ. Och om någon skulle göra en LastBil, och inte överrida vår GörOmKörning() så kommer bastypens (alltså Bil) metod att anropas och en omkörningkommer att göras om än kanske inte helt så optimalt som det önskas....

Det är bara att sätta igång och leka, sätt en massa breakpoints i de olika metoderna så ser du hur rätt metod kommer att användas...

- M

Medlem sedan jan. 20022 440 inlägg
#6

Anledningen till transactions är att jag först ska spara en resultatsfil.html i databasen och om det går bra spara informationen om resultatet, så om något går fel vill jag inte spara någonting. Jag hittade OleDbTransaction efter lite sök då jag höll på att bli tokig av att rensa databasen hela tiden vid testkörning.... Egentligen borde jag nog titta lite närmare på "Unit Test" men transactions får duga tillsvidare.

När det gäller ditt andra svar så gav det inte bara svar på det jag frågade utan även en vägvisare till hur jag ska få bort alla fula ifsatser! :)

Medlem sedan dec. 19996 721 inlägg
#7

Gladh skrev:

om jag nu då vill göra en omkörning på alla mina bilar i listan så skulle man ju kunna göra så här:

foreach(Bil bil in bilList)
{
   if(bil.GetType() == typeOf(SportBil))
      ((SportBil)bil).GörOmKörning2();
   if(bil.GetTYpe() == typeOf(Bil))
      bil.GörOmKörning();
}

Men hur snyggt är det och framför allt hur praktiskt är det, det kan ju faktiskt komma någon som skapar en LastBil som ärver från din Bil och lägger med den i listan, då kommer den aldrig att göra någon omkörning eftersom det alternativet inte finns med.

Men om vi istället har löst det så som vi har gjort med Virtual och override, så löser vi det så här.

foreach(Bil bil in bilList)
   bil.GörOmKörning();

Japp! Klockrent! Det här är ett exempel på en fundamental grundregel inom oo som populärt kallas "Tell, don't ask". Be objekten att utföra saker, i stället för att fråga dem om en massa. Som alla regler inom programmering så är det inget man måste följa slaviskt, men det är ett bra grundkoncept att ha i bakhuvudet.

Medlem sedan maj 20012 812 inlägg
#8

Catz skrev:

Anledningen till transactions är att jag först ska spara en resultatsfil.html i databasen och om det går bra spara informationen om resultatet, så om något går fel vill jag inte spara någonting. Jag hittade OleDbTransaction efter lite sök då jag höll på att bli tokig av att rensa databasen hela tiden vid testkörning.... Egentligen borde jag nog titta lite närmare på "Unit Test" men transactions får duga tillsvidare.

Det är precis ett sådant tillfälle som du skall använda dig av Transactioner, ALLT eller INGET skall sparas. Du lägger alla dina åtagande inom en Transaction (Det finns en ny speciell klass för detta i .NET 3.0 (eller kanske till och med 2.0) som förenklar det otroligt mycket, speciellt om du skall ha transactioner mot fler olika källor, så som databaser, köer och även Filesystemet i Vista (eller om det bara var mot nästa version av WindowsServer, jaja..). Det fungerar iprincip så här:

using(Transaction trans = new Transaction())
{
// Do all your magic stuff here, write to 100 off diffrent databases och queues

trans.Complett();
}

Du måste lägga till System.Transaction som referens, men den är så enkel att använda så det nästan är fusk. Kommer ihåg när man var tvungen att hålla på med COM+ komponenter för att få transaktioner över flera olika databaser eller till köer... de var tider det... ;)

Kom dock ihåg att din databas måste stödja transactioner annars hjälper det föga, så exempelvis Access kan du inte göra det på, men SQL Server går utmärkt...

- M

138 ms totalt · 3 externa anrop · v20260731065814-full.b746b907
0 ms — hämta forumlista (cache)
0 ms — hämta statistik (cache)
136 ms — hämta tråd, inlägg och bilagor (db)