Kirjoittaja: anttipanda
Kirjoitettu: 03.02.2006 – 28.10.2012
Tagit: ohjelmointitavat, koodi näytille, vinkki
Yksinkertain light-weight esimerkki geneeristen luokkien käytöstä.
Geneeristen tyypien voidaan luokka saada toimimaan samalla tavalla jokaiselle tietotyypille. Geneeriselle luokalle annetaan tyyppi (esim. T), ja tämän tyyppinimen avulla voidaan tuntemattoman tyyppiselle oliolle suorittaa toimintoja. Oliolle voidaan suorittaa kaikkia toimintoja, mitä Object-luokan oliolle.
Tällaiseen pinoon esimerkiksi voit tallentaa kaikkia Object-luokasta perittyjä olioita, eli siis kaikkia C#:n olioita! Toisin kuin ei-geneerisessä stackissa, haettuja olioita ei tarvitse jälkikäteen muuttaa oikean tyyppiseksi.
Stack.cs
/* Geneerinen Stack * Antti Karhu 2.2.2006 * * Yksinkertain light-weight esimerkki geneeristen luokkien käytöstä. * * Geneeristen tyypien voidaan luokka saada * toimimaan samalla tavalla jokaiselle tietotyypille. * Geneeriselle luokalle annetaan tyyppi (esim. T), * ja tämän tyyppinimen avulla voidaan tuntemattoman * tyyppiselle oliolle suorittaa toimintoja. * Oliolle voidaan suorittaa kaikkia toimintoja, * mitä Object-luokan oliolle. * * Tällaiseen pinoon esimerkiksi voit tallentaa * kaikkia Bbject-luokasta perittyjä olioita, * eli siis kaikkia C#:n olioita! Toisin kuin * ei-geneerisessä stackissa, haettuja olioita * ei tarvitse jälkikäteen muuttaa oikean tyyppiseksi. */ using System; namespace Stacktesti { //Tässä määritetään tyyppimuuttuja T, jolla //kuvataan luokassa käsiteltävän tiedon tyyppiä public class Stack<T> { //tässä muuttujassa pidetään päällimmäistä arvoa. private StackItem<T> topItem; public Stack() { topItem = null; } //parametriksi annettu T muuntuu siksi tyypiksi, //joka on asetettu luokan määrittelyn yhteydessä public void Push(T value) { //lisätään uusi olio, joka pistetään viittaamaan //edellisenä olleeseen päällimmäiseen olioon. topItem = new StackItem<T>(this.topItem, value); } public T Pop() { if (this.topItem == null) throw new StackException("Cannot pop from empty stack"); //otetaan talteen päällimmäisin arvo T returnValue = topItem.value; //vaihdetaan toisiksi päällimmäinen päällimmäiseksi //ja näin annetaan roskienkeruun tuhota päällimmäinen topItem = topItem.nextStackItem; return returnValue; } public T Peek() { if (this.topItem == null) throw new StackException("Cannot peek into empty stack"); //palautetaan vain päällimmeinen arvo return this.topItem.value; } /// <summary> /// Sisäinen luokka StackItem, joka sisältää arvon sekä viittauksen /// seuraavaan StackItemiin pinossa /// </summary> private class StackItem<U> { //viittaus seuraavaan StackItemiin public StackItem<U> nextStackItem; //arvo public U value; public StackItem(StackItem<U> nextItem, U value) { this.nextStackItem = nextItem; this.value = value; } } } //Omat poikkeusluokat on hyvä periä ApplicationException-luokasta. /// <summary> /// Poikkeusluokka jota käytetään Stacking kanssa. /// </summary> public class StackException : ApplicationException { //Jos oma poikkeusluokka ei //tarvitse muita toimintoja kuin mitä //ApplicationException-luokalla on, //niin toteutukseksi riittää vain, //kun kirjoitetaan jokaista //kantaluokan vastaavaa rakentajaa vastaavat //rakentajat ja kutsutaan niitä. public StackException() : base() { } public StackException(string message) : base(message) { } public StackException(string message, Exception innerException) : base(message, innerException) { } public StackException(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context) : base(info, context) { } } }
Program.cs
/* Geneerinen Stack, testiohjelma * Antti Karhu 2.2.2006 */ using System; namespace Stacktesti { /// <summary> /// Tämä luokka testaa geneeristä pinoamme /// </summary> class Program { static void Main(string[] args) { Stack<string> stack = new Stack<string>(); stack.Push("viesti0"); stack.Push("viesti1"); stack.Push("viesti2"); stack.Push("viesti3"); try { Console.WriteLine(stack.Pop()); Console.WriteLine(stack.Pop()); Console.WriteLine(stack.Peek()); Console.WriteLine(stack.Peek()); Console.WriteLine(stack.Pop()); Console.WriteLine(stack.Peek()); Console.WriteLine(stack.Peek()); Console.WriteLine(stack.Peek()); Console.WriteLine(stack.Pop()); Console.WriteLine(stack.Pop()); } catch (StackException ex) { Console.WriteLine(ex.Message); } try { Console.WriteLine(stack.Peek()); } catch (StackException ex) { Console.WriteLine(ex.Message); } } } }
Sinänsä ihan toimiva geneerisen luokan toteutuksen esimerkkinä, mutta kannattaa muistaa että C#:ssa on vakiona Stack toteutus System.Collections nimiavaruudessa.