PDA-applikationer med .NET: Lektion 5

Idag: Datatyper i .NET och i C#.

Klicka på startknappen i den lilla mediaspelaren ovan för att lyssna på lektionen. (Man kan behöva vänta en stund på att ljudfilen laddas ner.) Om mediaspelaren inte syns, eller om det inte fungerar av något annat skäl, kan man klicka här för att ladda ner mp3-filen (ca 35 minuter, ca 16 megabyte). Beroende på hur webbläsaren är konfigurerad kan det kräva ett separat mp3-spelarprogram av något slag.

Tänk på att lektionerna ger en översikt och introduktion. Du måste läsa i kursboken och arbeta med övningarna för att tillgodogöra dig kursen!

"Bild" 1: Repetition av repetitionen av klasser och objekt i Java

Samma program som i lektion 4: klasserna Person och ObjektExempel, i filen ObjektExempel.java.

Den rödmarkerade raden fungerar fortfarande inte.

    1   class Person {
    2       private int lön;
    3       private int bonus;
    4       public Person(int lön, int bonus) {
    5           this.lön = lön;
    6           this.bonus = bonus;
    7       }
    8       public int lönesumma() {
    9           return lön + bonus;
   10       }
   11   } // class Person
   12
   13   public class ObjektExempel {
   14       public static void main(String[] args) {
   15           int en_summa = Person.lönesumma();
   16           System.out.println("Summan = " + en_summa);
   17
   18           Person olle = new Person(17000, 200);
   19           Person kajsa = new Person(38000, 29000);
   20
   21           int en_annan_summa = olle.lönesumma();
   22           System.out.println("Olles lönesumma = " + en_annan_summa);
   23           int en_tredje_summa = kajsa.lönesumma();
   24           System.out.println("Kajsas lönesumma = " + en_tredje_summa);
   25       } // main
   26   } // class ObjektExempel

"Bild" 2: Utmatningen från programmet

(När man tagit bort de felaktiga raderna.)

Olles lönesumma = 17200
Kajsas lönesumma = 67000

"Bild" 3: Klasser och objekt i C#

Klasserna Person och ObjektExempel, i filen ObjektExempel.cs. Precis som i Java, utom de blåmarkerade orden.

Den rödmarkerade raden fungerar inte här heller.

Programmet fungerar inte i Pocket PC! Varför?

    1   class Person {
    2       private int lön;
    3       private int bonus;
    4       public Person(int lön, int bonus) {
    5           this.lön = lön;
    6           this.bonus = bonus;
    7       }
    8       public int lönesumma() {
    9           return lön + bonus;
   10       }
   11   } // class Person
   12
   13   public class ObjektExempel {
   14       public static void Main(System.String[] args) {
   15           int en_summa = Person.lönesumma();
   16           System.Console.WriteLine("Summan = " + en_summa);
   17
   18           Person olle = new Person(17000, 200);
   19           Person kajsa = new Person(38000, 29000);
   20
   21           int en_annan_summa = olle.lönesumma();
   22           System.Console.WriteLine("Olles lönesumma = " + en_annan_summa);
   23           int en_tredje_summa = kajsa.lönesumma();
   24           System.Console.WriteLine("Kajsas lönesumma = " + en_tredje_summa);
   25       } // Main
   26   } // class ObjektExempel

"Bild" 4: Egenskaper i Java

En ny variant av klassen Person, i filen Egenskaper.java:

De rödmarkerade raderna fungerar inte. Varför?

    1   class Person {
    2       private int lön;
    3       private int bonus;
    4       public Person(int lön, int bonus) {
    5           this.lön = lön;
    6           this.bonus = bonus;
    7       }
    8       public int lönesumma() {
    9           return lön + bonus;
   10       }
   11       public void setLön(int nyLön) {
   12           lön = nyLön;
   13       }
   14       public int getLön() {
   15           return lön;
   16       }
   17   } // class Person
   18
   19   public class Egenskaper {
   20       public static void main(String[] args) {
   21           Person kajsa = new Person(38000, 29000);
   22           kajsa.lön = 39000;
   23           System.out.println("Kajsas lön = " + kajsa.lön);
   24           kajsa.setLön(39000);
   25           System.out.println("Kajsas lön = " + kajsa.getLön());
   26       } // main
   27   } // class Egenskaper

"Bild" 5: Egenskaper i C#

C# har en särskild mekanism för hantering av egenskaper ("properties" på engelska).

Ännu en variant av klassen Person, i filen Egenskaper.cs:

    1   class Person {
    2       private int lönen;
    3       private int bonus;
    4       public Person(int lön, int bonus) {
    5           this.lönen = lön;
    6           this.bonus = bonus;
    7       }
    8       public int lönesumma() {
    9           return lönen + bonus;
   10       }
   11       public int lön {
   12           get { return lönen; }
   13           set { lönen = value; }
   14       }
   15   } // class Person
   16
   17   public class Egenskaper {
   18       public static void Main(System.String[] args) {
   19           Person kajsa = new Person(38000, 29000);
   20           kajsa.lön = 39000;
   21           System.Console.WriteLine("Kajsas lön = " + kajsa.lön);
   22       } // Main
   23   } // class Egenskaper

Bild 6: Värdetyper och referenstyper

I Java och C#: Exempel (se programmet nedan):

Variabler (x och y) av en värdetyp och (z och t) av en referenstyp

"Bild" 7: Värde- och referenstyper i C#

Klasserna Person och Referenstyper, i filen Referenstyper.cs.

(Det här funkar precis likadant i Java, och om man vill kan man titta på motsvarande program i Java: Referenstyper.java.)

    1   class Person {
    2       private int lönen;
    3       private int bonus;
    4       public Person(int lön, int bonus) {
    5           this.lönen = lön;
    6           this.bonus = bonus;
    7       }
    8       public int lönesumma() {
    9           return lönen + bonus;
   10       }
   11       public int lön {
   12           get { return lönen; }
   13           set { lönen = value; }
   14       }
   15   } // class Person
   16
   17   class Referenstyper {
   18       static void Main() {
   19           int x;
   20           int y;
   21           Person z;
   22           Person t;
   23
   24           x = 17;
   25           y = x;
   26           z = new Person(75, 100);
   27           t = z;
   28
   29           System.Console.WriteLine("Ändrar x till 42...");
   30           x = 42;
   31           System.Console.WriteLine("Nu har y värdet " + y + ".");
   32
   33           System.Console.WriteLine("Ändrar z:s lön till 42...");
   34           z.lön = 42;
   35           System.Console.WriteLine("Nu har t lönen " + t.lön + ".");
   36       } // Main
   37   } // class Referenstyper

"Bild" 8: Utmatningen från programmet

Ändrar x till 42...
Nu har y värdet 17.
Ändrar z:s lön till 42...
Nu har t lönen 42.

"Bild" 9: Metodanrop med värde- och referenstyper i Java

Klasserna Person och Anrop, i filen Anrop.cs:

    1	class Person {
    2	    private int lönen;
    3	    private int bonus;
    4	    public Person(int lön, int bonus) {
    5	        this.lönen = lön;
    6	        this.bonus = bonus;
    7	    }
    8	    public int lönesumma() {
    9	        return lönen + bonus;
   10	    }
   11	    public int lön {
   12	        get { return lönen; }
   13	        set { lönen = value; }
   14	    }
   15	} // class Person
   16	
   17	class Anrop {
   18	    static void tarEttVärde(int i) {
   19	        i = 99;
   20	    }
   21	
   22	    static void tarEnReferens(Person p) {
   23	        p.lön = 99;
   24	    }
   25	
   26	    static void Main() {
   27	        int x;
   28	        Person z;
   29	
   30	        x = 17;
   31	        z = new Person(75, 100);
   32	
   33	        System.Console.WriteLine("Före anropet: Nu har x värdet " + x + ".");
   34	        tarEttVärde(x);
   35	        System.Console.WriteLine("Efter anropet: Nu har x värdet " + x + ".");
   36	
   37	        System.Console.WriteLine("Före anropet: Nu har z lönen " + z.lön + ".");
   38	        tarEnReferens(z);
   39	        System.Console.WriteLine("Efter anropet: Nu har z lönen " + z.lön + ".");
   40	    } // Main
   41	} // class Anrop

"Bild" 10: Utmatningen från programmet

Före anropet: Nu har x värdet 17.
Efter anropet: Nu har x värdet 17.
Före anropet: Nu har z lönen 75.
Efter anropet: Nu har z lönen 99.

"Bild" 11: int är ett alias för System.Int32

    1   class Person {
    2       private System.Int32 lönen;
    3       private System.Int32 bonus;
    4       public Person(System.Int32 lön, System.Int32 bonus) {
    5           this.lönen = lön;
    6           this.bonus = bonus;
    7       }
    8       public System.Int32 lönesumma() {
    9           return lönen + bonus;
   10       }
   11       public System.Int32 lön {
   12           get { return lönen; }
   13           set { lönen = value; }
   14       }
   15   } // class Person

"Bild" 12: Några andra .NET-datatyper

.NET-namn C#-alias Visual Basic-alias Antal bitar Värden
System.Int32 int Integer 32 -2147483648 .. 2147483647
System.Int64 long Long 64 -922337203685477508 .. 922337203685477507
System.Single float Single 32 -3.402823e38 .. 3.402823e38
System.Double double Double 64 -1.79769313486232e308 .. 1.79769313486232e308
System.Boolean bool Boolean 8 true och false
System.Byte byte Byte 8 0 .. 255
System.Char char Char 16 Unicode-symboler
System.String string
System.Array
System.Object object

Bild 13: Egendefinierade värdetyper i C#: struct

Variabler (x och y) av en värdetyp och (z och t) av en annan värdetyp

"Bild" 14: Egendefinierade värdetyper i C#: struct

    1   struct Person {
    2       private int lönen;
    3       private int bonus;
    4       public Person(int lön, int bonus) {
    5           this.lönen = lön;
    6           this.bonus = bonus;
    7       }
    8       public int lönesumma() {
    9           return lönen + bonus;
   10       }
   11       public int lön {
   12           get { return lönen; }
   13           set { lönen = value; }
   14       }
   15   } // struct Person
   16
   17   class Värdetyper {
   18       static void Main() {
   19           int x;
   20           int y;
   21           Person z;
   22           Person t;
   23
   24           x = 17;
   25           y = x;
   26           z = new Person(75, 100);
   27           t = z;
   28
   29           System.Console.WriteLine("Ändrar x till 42...");
   30           x = 42;
   31           System.Console.WriteLine("Nu har y värdet " + y + ".");
   32
   33           System.Console.WriteLine("Ändrar z:s lön till 42...");
   34           z.lön = 42;
   35           System.Console.WriteLine("Nu har t lönen " + t.lön + ".");
   36       } // Main
   37   } // class Värdetyper

"Bild" 15: Utmatningen från programmet

Ändrar x till 42...
Nu har y värdet 17.
Ändrar z:s lön till 42...
Nu har t lönen 75.

"Bild" 16: Arv i C#

Största skillnaden mot Java: Man skriver kolon i stället för nyckelordet extends.

Klasserna Djur, Fågel och Fisk från filen Arv1.cs:

    1   class Djur {
    2       private System.String namn;
    3       private int vikt;
    4   } // class Djur
    5
    6   class Fågel : Djur {
    7       private int vingspann;
    8   } // class Fågel
    9
   10   class Fisk : Djur {
   11       private int antalFenor;
   12   } // class Fisk

Bild 17: Arv

Basklassen Djur, med subklasserna Fisk och Fågel

Bild 18: Arv med klasser sedda som mängder

Från http://www.databasteknik.se/webbkursen/oo-grunder/index.html:

Arv av klasser som mängder

"Bild" 19: Polymorfism i C#

Klassen Arv1 från filen Arv1.cs:

De rödmarkerade raderna fungerar inte.

   14   class Arv1 {
   15       static void Main() {
   16           Djur djur1 = new Djur();
   17           Djur djur2 = new Fågel();
   18           Djur djur3 = new Fisk();
   19           Djur djur4 = djur1;
   20           Djur djur5 = djur2;
   21           Fågel fågel1 = new Fågel();
   22           Fågel fågel2 = new Djur();
   23           Fisk fisk1 = new Fisk();
   24           Fisk fisk2 = new Fågel();
   25           Djur djur6 = fisk1;
   26           Fågel fågel3 = fisk1;
   27           Fågel fågel4 = djur1;
   28           Fågel fågel5 = (Fågel)djur2;
   29       }
   30   } // class Arv1

"Bild" 20: Felmeddelanden från C#-kompilatorn

Arv1.cs(22,15): error CS0029: Cannot implicitly convert type `Djur' to `Fågel'
Arv1.cs(24,14): error CS0029: Cannot implicitly convert type `Fågel' to `Fisk'
Arv1.cs(26,15): error CS0029: Cannot implicitly convert type `Fisk' to `Fågel'
Arv1.cs(27,15): error CS0029: Cannot implicitly convert type `Djur' to `Fågel'
Arv1.cs(28,15): warning CS0219: The variable `fågel5' is assigned but its value is never used
Compilation failed: 4 error(s), 1 warnings

Bild 21: Polymorfismen uppritad

Variabler och objekt i programmet Arv1

"Bild" 22: Mera metoder

Metoden ToString och nyckelorden new och override.

Klassen Arv2 från filen Arv2.cs:

    1   class Djur {
    2       private System.String namn;
    3       private int vikt;
    4       public Djur(System.String namn) { this.namn = namn; vikt = 1; }
    5       public Djur() : this("Namnlöst djur") { }
    6       public System.String beskrivning() { return "Ett djur som heter " + namn; }
    7   } // class Djur
    8
    9   class Fågel : Djur {
   10       private int vingspann;
   11       public Fågel(System.String namn, int vingspann) : base(namn) { this.vingspann = vingspann; }
   12       public Fågel() : this("Namnlös fågel", 10) { }
   13       public new System.String ToString() { return base.ToString() + "(" + vingspann + ")"; }
   14   } // class Fågel
   15
   16   class Fisk : Djur {
   17       private int antalFenor;
   18       public Fisk(System.String namn, int antalFenor) : base(namn) { this.antalFenor = antalFenor; }
   19       public Fisk() : this("Namnlös fisk", 10) { }
   20       public override System.String ToString() { return base.ToString() + "(" + antalFenor + ")"; }
   21   } // class Fisk
   22
   23   class Arv2 {
   24       static void Main() {
   25           Djur djur1 = new Djur("Algot");
   26           System.Console.WriteLine("Djuret djur1: " + djur1 + " = " + djur1.beskrivning());
   27           Fågel fågel1 = new Fågel();
   28           System.Console.WriteLine("Fågeln fågel1: " + fågel1 + " = " + fågel1.beskrivning());
   29           Fisk fisk1 = new Fisk("Sigge", 5);
   30           System.Console.WriteLine("Fisken fisk1: " + fisk1 + " = " + fisk1.beskrivning());
   31       }
   32   } // class Arv2

"Bild" 23: Utmatningen från programmet

Fast inte på Pocket PC.

Djuret djur1: Djur = Ett djur som heter Algot
Fågeln fågel1: Fågel = Ett djur som heter Namnlös fågel
Fisken fisk1: Fisk(5) = Ett djur som heter Sigge

"Bild" 24: Mono

Alla C#-exemplen i den här lektionen är provkörda med Visual Studio, men också med Mono under operativsystemet Linux. Mono är en öppen-källkods-implementation av .NET, som gör att det går att både utveckla och köra .NET-program inte bara på Windows utan också på bland annat Linux och MacOS.

Än så länge klarar Mono inte av GUI-klasserna i Windows (System.Windows.Forms.Form med flera), uatn man måste använda helt andra GUI-klasser. De vanliga .NET-program som man skriver för Windows, till exempel de handdatorprogram som man skriver i den här kursen, använder ju oftast Windows-GUI-klasser, så de går tyvärr inte att köra med Mono. Men som synes så klarar Mono själva grund-.NET och grund-C#, med datatyper och konsol-I/O.

Mono kan laddas ner gratis från http://www.mono-project.com/.

Läsanvisningar

Den här lektionen motsvaras av kapitel 3, The .NET Type System, i kursboken.

Handlar om hur data (dvs objekt och värden) fungerar i C# och mer allmänt i .NET. Kapitlet tar upp många detaljer om hur C# och .NET fungerar internt, som man inte behöver kunna för att skriva enkla program. Om man kommer ihåg sin Java kan det i nödfall räcka med att data i C# hanteras "nästan precis som i Java", men med vissa ganska stora undantag (som till exempel struct).

Här är i alla fall några frågor som kan användas som instuderingsfrågor:

  1. Det står en massa i kapitlet om typsystemet i .NET. Varför det? Det är ju C# vi ska programmera i?
  2. Vad är en strukturtyp (struct)?
  3. Vad är en referenstyp?
  4. Hur skiljer sig strukturtyper och referenstyper?
  5. De enklaste datatyperna som int och float, är de referenstyper eller strukturtyper?
  6. Strängar lagras i C# med datatypen string, som är ett alias för .NET-datatypen System.String. Är det en referenstyp eller en strukturtyp?
  7. Strängar i C# är oföränderliga ("immutable"). Vad betyder det?
  8. Ett alternativ till string är System.Stringbuilder. Vad har man den till?
  9. Skulle inte vanliga string fungera lika bra?
  10. Om h är en variabel av typen int, och hh är en variabel av typen long, kan man skriva hh = h; men inte h = hh;. Varför kan man inte det?
  11. Vad ska man skriva i stället?
  12. Vilket undantag ("exception") kan uppkomma när den koden körs?
  13. Skräpsamling ("garbage collection") innebär att systemet automatiskt städar bort data som inte längre används. I sina klasser kan man skapa två metoder som har med skräpsamlingen att göra: Finalize och Dispose. Vad gör dessa metoder?
  14. Finalize är det interna .NET-namnet på metoden. I C#-koden som man skriver ska den heta något annat. Vad?
Om du vill skriva svar på instuderingsfrågorna, räcker det för de flesta frågorna med en eller några få meningar.

Programmeringsövningar

Föregående lektion | Lektionslista | Nästa lektion


Thomas Padron-McCarthy (Thomas.Padron-McCarthy@tech.oru.se), 3 oktober 2005