Programozás 2 Objektum Orientált Programozás C# nyelven utolsó változtatás 2008.05.02.
.NET
C# - Microsoft találmánya a .NET platform számára. A C++ 'továbbfejlesztése' .NET – hálózaton elosztott programok együttműködése Előnyei:
Nyelv független, fordítás közös közbenső nyelvre (Common Intermediate Language), amit futás közben fordít le a rendszer gépi kódra (Just In Time compiler) potenciális egyszerűsítés: kódok csoportjai csak egy-egy helyen vannak különböző típusú (Windows-os) eszközök ugyanazzal a kóddal támogathatóak Microsoft (és mások) könnyebben szabályozhatják ki mikor mit futtathat Nyílt szabványokon (is) alapul: XML (Extensible Markup Language ) és SOAP (eredetileg 'Simple Object Access Protocol' ')
Hátrányai:
Erőforrás igénye a Common Language Runtime miatt nagy Windows specifikus (van linux-os open source próbálkozás MONO, DotGNU ), de ezek nem teljesek (.NET 1.1 APIs teljes, 2.0 – 96%, 3 és 3.5 -alfa) Egyes függvények a Base Class Library-ben Microsoft szabadalommal védettek Már most több, mint 6000 függvénye van
Az első C# program
Egy elso.cs nevű fájlba írjuk be a következőket: using System; // ki és bevitelhez a namespace class Koszones // minden vmilyen osztályban van { // ide nem kéne public, mert a Main()-t nem hívhatjuk meg // a static azt jelenti, hogy objektum létrehozás nélkül is használható public static void Main(string[] args) // itt kezdődik a futás
{ // args[0] az első paraméter, nem a program neve // kiiratás {0} az első behelyettesítendő paraméter
Console.WriteLine("Szia {0}!", args[0]); // itt az args[0] Console.ReadLine(); // csak, hogy az ablak ne csukódjon be a Visual Studio-
ból futtatva.
} }
C# alap típusok
Boolean – csak true, vagy false lehet. Egészek: sbyte
8
-128 … 128
byte
8
0 … 256
short
16
-32768 to 32767
ushort
16
0...65535
int
32
-2147483648 to 2147483647
uint
32
0…4294967295
long
64
-9223372036854775808 to 9223372036854775807
ulong
64
0 to 18446744073709551615
char
16
0..65535
C# alap típusok
valós számok név
tartomány
float double
hossz értékes jegyek 32 7 64 15
decimal
128
1.0 x 10-28 to 7.9 x 1028
28-29
1.5 x 10-45 to 3.4 x 1038 5.0 x 10-324 to 1.7 x 10308
stringek
escape sorozatok: \' \" \\ \0 (nem azonos a null értékkel) \a \b \f \n \r \t
\v
C# típusok
Minden típus a System.Object osztályból van leszármaztatva, ezért vannak metódusai Pl. int a = 3; string s = a.ToString();
Tömbök (példák) int[] myInts = { 5, 10, 15 }; // integer tömb myInts[2] myInts[2] = 9;
ekvivalens deklaráció és definíció: int[] myInts = new int[] { 5, 10, 15 }; string[] myStrings = new string[3]; assert(string[0]) == null)
bool[][] myBools = new bool[2][]; //bool tömböket tartalmazó tömb ('jagged' array) myBools[0] = new bool[2]; // az egyes tö tömbö mbök dimenzió dimenziója myBools[1] = new bool[1]; // kü különbö nbözhet
double[,] myDoubles = new double[2, 2]; // két indexű tömb myDoubles[0,2] myDoubles[0,2] = 3.16;
Felsorolási típusok (enum)
Feltételes és ciklus utasítások
Ami a C++ -ban is megvan, különbségekkel: 1.
2.
switch() argumentuma lehet enum, egész és string Van foreach ciklus. pl: string[] gyumolcs = {"Alma", "Körte", "Szilva"}; foreach (string a in gyumolcs) { Console.WriteLine("{0} ", a); }
C# operátorok Kategória
operátorok
asszociativitás
elsődleges
(x) x.y f(x) a[x] x++ x– new typeof sizeof checked unchecked
balra
unáris
+ - ! ~ ++x --x (T)x
balra
szorzás, stb
* / %
balra
összeadás
+-
balra
eltolás
<< >>
balra
relációs
< > <= >=
balra
egyenlőség
== !=
jobbra
logikai ÉS
&
balra
logikai VAGY
|
balra
kizáró VAGY
^
balra
feltételes ÉS
&&
balra
feltételes VAGY
||
balra
feltétel
… ? ... : …
jobbra
értékadás
= *= /= %= += -= <<= >>= &= ^= |=
jobbra
Nem static metódusok (függvények)
using System; class EgyModszeresOsztaly { public static void Main() { string valasztas;
// static: nem kell objektumot létrehozni hozzá (mint a C++-ban)
EgyModszeresOsztaly om = new EgyModszeresOsztaly(); do {
valasztas = om.Valaszt(); ...
} while ( valasztas != 'Q' && valasztas != 'q');
}
} string Valaszt() // nem static: objektum kell hozzá. ezért van a new a Main-ben { // nem public: kívülről nem érhető el string valasztas; valasztas = Console.ReadLine(); return valasztas; }
Osztályok
Class
Minden elem (objektum, változó, konstans, függvény, stb) valamilyen osztályban van A hozzáférési jogokat minden elemhez meg kell adni. Ezek lehetnek:
public
bárki hozzáférhet
protected
csak a class és leszármaztatottjai férhetnek hozzá
internal
csak ebből a gyűjteményből (azaz az együtt fordított fájlokból – ún. assembly-ből) hozzáférhető, de itt mindenki számára (azaz itt olyan, mintha public lenne)
protected internal
ebben az assembly-ben public, más assemblyk-ben protected
private
csak maga az osztály férhet hozzá
az osztály elemei lehetnek static-ok. Ezek használatához nem kell objektumot létrehozni.
Osztályok 2
constructor – public, private, static – nincs paramétere, nem hívható explicit módon (new-val) destructor – nincs paramétere, nem hívható meg, nem lehet public, stb konstans elemek – definíció szerint static-ek, de nem szabad a static kulcsszót eléjük írni:
Pl.: public const int A=175; public const int B = A + 6;
A static elemek is megváltoztathatóak de ez letiltható: public static readonly int piros;
A readonly elemek értékét csak deklarációban, illetve constructorban lehet megadni:
Osztályok 3. class Color { internal ushort redPart; internal ushort bluePart; internal ushort greenPart; public Color(ushort red, ushort blue, ushort green) { redPart = red; bluePart = blue; greenPart = green; } public static readonly Color Red = new Color(0xFF, 0, 0); public static readonly Color Blue = new Color(0, 0xFF, 0); public static readonly Color Green = new Color(0, 0, 0xFF); public static readonly Color White = new Color(0xFF, 0xFF, 0xFF); }
Függvényparaméterek
Érték (value) paraméterek int F(int i) { return 2 * i; } -> int k = F(12); int j = F(k);
ref paraméterek – referencia int F( ref int i) { return 2 * i;} -> int i =4; int k = F(i); // i == 8
out paraméterek – csak output a belső paraméter értékét adja át az out paraméterben class C; int F( out C c) { C cc; … c = cc; return 1; }
params paraméterek – változó hosszúságú int F(params int [] Param1) { foreach(int P in Param1) {…} return v; }
Túlterhelés: A függvények argumentumainak száma, típusa, módosítói különböznek. Pl.
Túlterhelés - Overloading using System; class Test { static void F() { Console.WriteLine("F()"); } static void F(object o) { Console.WriteLine("F(object)"); } static void F(int value) { Console.WriteLine("F(int)"); } static void F(ref int value) { Console.WriteLine("F(ref int)"); } static void F(int a, int b) { Console.WriteLine("F(int, int)"); } static void F(int[] values) { Console.WriteLine("F(int[])"); } static void Main() { F(); F(1); int i = 10; F(ref i); F((object)1); F(1, 2); F(new int[] {1, 2, 3}); } }
Property-k
úgy használható mintha változó lenne, de valójában függvényhívás: public class Gomb { private string szoveg; public string Szoveg { get { return szoveg; } // olvasás: amikor a Szöveg egy értékadás jobb oldalán szerepel set { caption = value; Repaint(); } // írás: ha a Szöveg egy értékadás bal oldalán szerepel // value – az értékadás jobb oldaláról származó érték neve a set -en belül // a compiler ezt a nevet várja } void UjraRajzol() { … } Gomb b = new Gomb(); b.Szoveg = "Kilépés"; // ez egyúttal újra is rajzolja a szöveget a gombra }
Indexer-ek
valamely osztá osztály úgy kezelhető kezelhető, mintha tö tömb lenne. lenne. rá ráadá adásul sul nem is csak int argumentummal: argumentummal: class AsszociativIntTomb { private int [] _arr; _arr; pubkic AsszociativIntTomb( AsszociativIntTomb(int size) { _arr = new int[ int[size]; size]; } // ez az indexer nincs sajá int this[string s] saját neve, csak a this haszná használható lható // ugyanú { ugyanúgy tú túlterhelhető lterhelhető, mint bá bármely má más fü függvé ggvény get { int i = int.Parse(s); // a stringstring-ből integerinteger-t csiná csinál return _arr[i]; } set { int i = int.Parse(s); _arr[i] = value; } } }
Haszná Használata: AsszociativIntTomb tomb = new AsszociativIntTomb(3); AsszociativIntTomb(3); tomb["1"] = 123;
Események
Pl. egy gombnyomás: public delegate void EsemenyKezelo(object sender, System.EventArgs e); // a delegate egy olyan típust jelöl, ami egy függvényt tartalmaz (C++ : egy függvényre mutató pointer) public class Gomb { public event EsemenyKezelo Click; // a fent definiá definiált delegate tí típusú pusú változó ltozó public void Reset() { Click = null; } }
Click használata: kizárólag += vagy -= bal oldalán szerepelhet. += hozzáad egy esemény kezelőt, -= elvesz egyet. Pl. : void Gomb_Kattintas(object sender, System.EventArgs e) { // csinál valamit } Gomb gomb1 = new Gomb(); gomb1.Click +=.new EsemenyKezelo(Gomb_Kattintas);
Lehetséges saját esemény hozzáadó, ill. eltávolító függvényt is defininiálni.
Leszármaztatás using System; abstract class A // absztrakt: nem lehet objektumot lé létrehozni belő belőle { public abstract void F(); // nincs megadva mit csiná csinál } class B : A { public override void F() // átdefiniá tdefiniálva { Console.WriteLine(" B.F"); Console.WriteLine("B } public virtual void G() // virtual – átdefiniá tdefiniálható lható a leszá leszármaztatott osztá osztályban { Console.WriteLine(" B.G"); Console.WriteLine("B } } class C: B { public override void G() // az átdefiniá tdefiniáláshoz kell az override { base.F (); // a szü base.F(); szülő osztá osztály mó módszere Console.WriteLine(" C.G"); Console.WriteLine("C } }
struct
Hasonló az osztályhoz, vagy az interfaceekhez de:
nem lehet leszármaztatni belőle érték-ként adódik át (osztály referenciaként) stack-en tárolja
időnként sok allokációt takaríthatunk meg vele
interface-ek módszereket, property-ket, indexer-eket és event-eket tartalmazhat. Pl. interface IPelda { string this[int index] { get; set; } event EventHandler E; void F(int v); string P { get; set; } } public delegate void EventHandler(object sender, EventArgs e); Az interface-ben a mezők nincsenek megvalósítva
interface-k 2.
InterfaceInterface-ekkel oldható oldható meg a tö többszö bbszörös leszá leszármaztatá rmaztatás. Egy osztá osztály csak 1 osztá osztálybó lyból, de bá bármennyi interfaceinterface-ből szá származtatható rmaztatható le: class A { virtual public void F(inti) F(inti) { … } } interface IPelda1 { void P1(int i); } interface IPelda2 { void P2(string s); } class B : A, IPelda1, IPelda2 { … public override void F() { … } // AA-ból public void P1(int i) { … } // implicit interface elem IPelda1IPelda1-ból void IPelda2.P2(string s; ) { … } // explicit interface elem IPelda1IPelda1-ból }
Hívásaik: aik: class Test { static void Main() { B b = new B(); b.F(); b.F(); b. P1(3); b.P2("alma") // error: no such method. az explicit elemet nem lehet meghí gy! meghívni így! IPelda2 ipelda2 = b; // a leszá leszármaztatá rmaztatás miatt b egyú egyúttal IPelda2 is ipelda2.P2("alma"); // ez má már jó jó } }
C# - C++ összehasonlítás
Mindkettőben a kis és nagybetű különböző. de C#ban Nincsenek globális változók, vagy függvények, minden vmilyen osztályon belül van Egy blokk lokális változói nem fedhetik el a blokkon kívülieket A bool típus nem konvertálható más típussá Mutatók által mutatott memóriát csak unsafe jelölésű szakaszokban lehet használni, ott is csak ha megfelelő engedély van rá. (Mutatót használni máshol is lehet, de az általa mutatott memóriát/változót nem)
C# - összehasonlítása a C++ -al
A 0 indexű parancssori paraméter a C++ ban az 1 indexű lenne (a program neve nincs a paraméterek között) A memóriában automatikus szemétösszegyűjtés van. A csak absztrakt függvényeket tartalmazó absztrakt osztály neve nem class, hanem interface Nincs többszörös leszármaztatás class-szal, de van interface-szel struct: mint a class, de c#-ban nem lehet sem őt magát, sem belőle leszármaztatni. (de a struct-ok is a System.Object leszármazottai) Nem lehet paraméter nélküli constructor-a. Ha nem adunk meg constructort a változók default értéket (pl. 0, null) kapnak. Típusok közötti konverzió általában csak explicit lehet. (kivétel pl. leszármaztatás, integer) Felsorolásos típusoknak saját namespace-e van properties A típusokhoz meta-infomációk tartoznak
C#
Részleges osztály definíciók – több fájlra eloszthatóak (így pl. csak azt látjuk, ami abban a fájlban érdekes) PL. legyen az Univerzum osztály két fájlban (uni1.cs és uni2.cs) definiálva.
partial class példa
Az univ1.cs fájlban public partial class Univerzum { public Univerzum() { _azon = 0; } }
Az univ2.cs fájlban public partial class Univerzum { private int _azon; }
C#
Generics – futás közben az aktuális típus felhasználásával jönnek létre (C++ template-ek fordítási időben)