• Shuffle
    Toggle On
    Toggle Off
  • Alphabetize
    Toggle On
    Toggle Off
  • Front First
    Toggle On
    Toggle Off
  • Both Sides
    Toggle On
    Toggle Off
  • Read
    Toggle On
    Toggle Off
Reading...
Front

Card Range To Study

through

image

Play button

image

Play button

image

Progress

1/30

Click to flip

Use LEFT and RIGHT arrow keys to navigate between flashcards;

Use UP and DOWN arrow keys to flip the card;

H to show hint;

A reads text to speech;

30 Cards in this Set

  • Front
  • Back
metody statyczne - odwoływanie się do pól klasy.
Kiedy definiujesz statyczną metodę nie może ona korzystać z żadnych pól zdefiniowanych w klasie. Chyba ,że pola te są też statyczne. Czyli statyczne metody mogą odwoływać się tylko do innych statycznych metod i pól. Niestatyczne pola i metody wymagają utworzenia obiektu, do których będą one odwoływane.

class Arytmetyka {
public static int Dodawanie(int a, int b)
{
return a + b;
}
}

int wynik = Arytmetyka.Dodawanie(1, 10);

Ststyczna metoda nie musi być w klasie statycznej, moze byc w zwyklej klasie.
const
Używając słowa const też deklarujesz pole statyczne tyle ,że wartość tego pola nigdy nie ulegnie zmianie. Const to skrót od constant co po angielsku znaczy stała.

Const nie używa słowa kluczowego static ,ale nie zmienia to faktu ,że jest ona statyczna.

Stałymi mogą być tylko typy: byte, char, short, int, long, float, double, decimal, bool, string oraz typ wyliczeniowy oraz typy referencyjne.
Klasa statyczna - co może zawierać.
W klasie statycznej mogą znajdować się tylko pola statyczne. Aby stworzyć klasę statyczną wystarczy dopisać słowo static przed słowem class.
W klasie statycznej może znajdować się konstruktor pod warunkiem ,że on też będzie statyczny.

Statyczny konstruktor
Jeśli w klasie znajduje się statyczny konstruktor ,zostanie on wywołany przed utworzeniem jakiegokolwiek egzemplarza klasy.

Nie można dokładnie określić momentu wywołania konstruktora statycznego ,ale wiadomo ,że ma to miejsce po uruchomieniu programu ,ale przed utworzeniem egzemplarza tej klasy.

class Osoba {
static Osoba()
{
Name = "Stefan";
}
private static string Name;
}
Konstruktor statyczny nie ma żadnego modyfikatora dostępu i nie może mieć. Statyczny konstruktor może operować tylko na statycznych polach.
Klasa anonimowa
Klasa anonimowa jest to klasa, która nie posiada własnej nazwy (albo przynajmniej kompilator ci tego nie powie, bo jednak jakąś nazwę klasa musi mieć ). Jest ona przydatna przy wyrażeniach, zapytaniach i typach zwracanych przez LINQ.

Możesz utworzyć anonimowy obiekt poprzez słowo kluczowe new oraz dwa nawiasy klamrowe, w których możesz napisać jakiekolwiek pola i wartości do nich.

var AnonimowyObiekt = new { Name = "Zdzisław", age = "23" };

Ponieważ nie wiesz do jakiej klasy jest przypisany ten obiekt musi tutaj być użyte słowo kluczowe var.

Klasy anonimowe mogą posiadać tylko pola publiczne .Wszystkie te pola muszą być zainicjalizowane . Żadne pola nie mogą być statyczne. Nie mogą zawierać metod.
Przepełnienie stosu i sterty - jakie exceptiony lecą.
Jeśli chodzi o wyjątki. W wypadku przepełnienia stosu otrzymamy wyjątek “StackOverflowException” , a w wypadku przepełnia sterty “OutOfMemoryException”. Sterta ani stos nie mają nieskończonej ilości miejsca i zazwyczaj te wyjątki są sygnałem , że program się zapętlił np. utworzył kilkanaście tysięcy obiektów na stercie.
Wartość null.
W C# możesz przypisać wartość null do jakiegokolwiek typu referencyjnego. Wartość null będzie znaczyła, że zmienna nie referuje się do żadnego obiektu przechowywanego w pamięci.

Wartość null jest znakiem tego , że dana zmienna nie przechowuje referencji. Czyli wartość null nie może być przypisana do typu wartościowego ponieważ null nie jest reprezentacją wartości.
Zmienne z wartością null - typy nullable
W C# istnieje jednak modyfikator, który pozwala na tworzenie zmiennych z wartością null . Te zmienne zachowują się w podobny sposób do oryginalnych typów z tym , że można do nich przypisać wartość null.

Warto zaznaczyć ,że ten specjalne typy wartościowe wciąż są typami wartościowymi. To ,że nagle do typów wartościowym możemy przypisać null nie znaczy ,że magicznie on stał się typem referencyjnym. Tak naprawdę dzieje się tutaj dużo magii kompilatora której nie widzimy.

Zmienne te deklaruje się za pomocą znaku zapytania, który powinien być napisany zaraz po typie bez spacji.
bool? b = null;
int? bb = null;
float? bbb = null;
Teraz możesz sprawdzać, czy dana zmienna ma wartość czy nie.

if (b == null)
b = true;
Można przypisać wartość z typu int na int? , ale operacja w drugą stronę jest niewykonalna. Typ int nie jest w stanie obsłużyć wszystkich wartości z int?. W takim wypadku pozostaje rzutowanie.
if (!b.HasValue)
b = true;
Ref
Jeśli dopiszesz do parametru słowo kluczowe ref , parametr stają się rzeczywiście tylko aliasem do metody. Czyli jakakolwiek jego zmiana w metodzie zostanie zachowana na zawsze. Dzieje się tak ponieważ parametr w metodzie jest referencją do tego samego obiektu ,a nie kopii.
static void Zmienie(ref Cuboid cuboid, ref int liczba, ref string napis)
{
cuboid = new Cuboid(44, 555, 666);
liczba--;
napis = "1234567890qwertyuiopasdfghj";
}

Pamiętaj, że zmienne, zanim wyślesz je do metody muszą mieć przypisane wartości.

Wysyłając też podajemy ref
Out
W metodzie z parametrem ref , parametr musi mieć przypisaną wartość zanim zostanie wywołana metoda. Może jednak chciałbyś, by metoda operowana na niezainicjowanej zmiennej i ją zmieniła. Właśnie do tego celu służy słowo kluczowe “out”.

Słowo kluczowe out w działaniu jest zbliżone do ref. Argument jest aliasem dla parametru metody.

Kiedy tworzysz metodę z parametrem out. Pamiętaj aby w trakcie działania metoda przypisała parametrowi out jakąś domyślną wartość w jakimkolwiek ciągu operacji wewnątrz metody. Jednym słowem parametr zawsze musi wrócić z przypisaną wartością

static void Zmienie2(out int liczba)
{
liczba = 121;
}
int f;
Zmienie2(out f);
Przykładem metody, gdzie wstępują parametry out jest np. metoda int.TryParse(). Znasz metodę Parse(), która zmienia łańcuch znaków na liczbę. Metoda ta najpierw sprawdza, czy dany łańcuch może być zmieniony na liczbę , a potem przypisuje do niej wartość.
System.Object
Wszystkie klasy i struktury dziedziczą po typie object. Możesz też użyć typu object do stworzenia zmiennej, która może referować do każdego typu.

System.Object obj2;
object obj;
W kodzie System.Object i object znaczą dokładnie to samo.

Object może przechowywać referencje do tego samego obiektu na stercie. Ponieważ wszystkie klasy nawet te utworzone przez nas są również typem object ,taka operacja jest prawidłowa.
Boxing
Boxing pakowanie
Jak właśnie widać zmienne object mogą referować się do jakiekolwiek obiektu referencyjnego. Mogą też przechowywać typy wartościowe.

int a = 121;
object ob = a;
Jednak to proste wyrażenie wymaga wyjaśnienia. Zmienne typu wartościowego żyją na stosie , a zmienna object żyje na stercie, czyli ona jest typu referencyjnego . W wyniku tej operacji wartość ze stosu zmiennej “a” zostanie skopiowana na stertę i referencyjnie powiązana z zmienną typu object. Ta operacja nazywa się boxing.


Aby zaradzić takiej sytuacji mamy do dyspozycji “rzutowanie” (cast). Jest to operacja, która sprawdza czy dany typ może być przekonwertowany na inny. Rzutowanie wykonuje się poprzez dopisanie nawiasów , a w nich typu, na który nasza zmienna mam być przekonwertowana.

int a = 121;
object ob = a;
int b = (int)ob
as
Operator "as" czyli jako
Moim zdaniem bardziej użytecznym operatorem jest jednak operator “as”. Zwłaszcza , że zobaczysz go jeszcze nieraz.

Do działania potrzebuje tych samych operandów co operator is ,ale jego działania jest inne. Słowo kluczowe “as” sprawdza najpierw, czy operacja rzutowania może się wykonać. Jeśli operacja może zostać wykonana następuje rzutowanie. W przeciwnym wypadku operator zwróci referencje bądź wartość null.
is
Operator "is" czyli “czy jest”
Operator is potrafi zweryfikować, czy dany obiekt jest danego typu bądź jest synem tej klasy (polimorfizm)

object o = new Cuboid(2, 4, 5);
int objetosc;
if (o is Cuboid)
{
Cuboid temp = (Cuboid)o;
objetosc = temp.Volume();
}
Operator do swojego działania potrzebuje dwóch operandów: obiekt , który chcemy sprawdzić i nazwę typu.

Jeśli dany obiekt jest danym typem bądź dziedziczy po nim wyrażenie, to zwróci wartość logiczną true.

W ten sposób kod w bloku if wykona się tylko wtedy, gdy rzeczywiście zmienna "o" przechowuje typ klasy Cuboid.
Struktury
Struktury to typ wartościowy a nie referencyjny.

Podstawową różnicą pomiędzy strukturą i klasą jest to, że struktury nie obsługują dziedziczenia.
Tak, czy siak oczywiście możemy tworzyć swoje własne struktury.


bool System.Boolean Struktura
byte System.Byte Struktura
decimal System.Decimal Struktura
double System.Double Struktura
float System.Single Struktura
int System.Int32 Struktura
long System.Int64 Struktura
sbyte System.SByte Struktura
short System.Int16 Struktura
uint System.UInt32 Struktura
ulong System.UInt64 Struktura
ushort System.UInt16 Struktura
object System.Object Klasa
string System.String Klasa
Tablice
Inicjalizowanie wartości w tablicy
Kiedy tworzysz instancje tablicy wszystkiej jej elementy mają domyślne wartości. Oczywiście możesz podać swoje wartości w trakcie inicjacji. Podajesz je w nawiasach klamrowych zaraz po stworzeniu instancji.

int[] dawaj = new int[3] { 1, 2, 3};
int[] dawaj2 = new int[] { 1, 2, 3, 4, 6, 7, 8, 9 };

int[] numery = new int[3] { 9, 8, 7 }; ;
for (int i = 0; i < 3; i++)
{
Console.WriteLine(numery[i]);
}
Jednak do użycia tablic w pętli for musimy znać jej wielkość. Jak można ją pobrać?

Wszystkie tablice są z instancją klasy System.Array dzięki temu mamy do dyspozycji kilka przydatnych właściwości i metod.
Jedną z przydatnych właściwości jest właściwość Lenght określająca wielkość tablicy.

Skoro użytkownik może podać dynamicznie wielkość tablicy dobrze byłoby tą wielkość jakoś później przechwycić.

for (int i = 0; i < numery.Length; i++)
{
Console.WriteLine(numery[i]);
}
foreach
Warto byłoby wspomnieć o zmiennej w pętli foreach. Może ona być zmienną lokalną var. Dzięki temu kompilator ustali za ciebie typ elementów w danej tablicy. Jest to przydatne, gdy nie znasz typów elementów w tablicy.

Tablica może np. zawierać w sobie anonimowe obiekty.

var osoby =new[] {
new {Name="Zdzisław",Wiek=22},
new {Name="Kaśka",Wiek=19}
};
foreach (var osoba in osoby)
{
Console.WriteLine(osoba.Name);
Console.WriteLine("\t" + osoba.Wiek);
}
Przydatne jest to też wtedy, gdy nie chcesz zapoznawać z jakim typem masz do czynienia.
virtual i override
Metoda, która celowo ma być nadpisana jest metodą wirtualną, to po pierwsze. Po drugie, nadpisywanie metody jest to mechanizm, który oferuje różne implementacje dla tej samej metody. Cel metody jest zawsze taki sam tylko dostosowany do danego obiektu.

Przysłaniając metodę tak naprawdę całkowicie ją zastępujemy i może ona w ogóle wykonywać inne polecenie.

Nadpisywanie metod jest często spotykanym mechanizmem w programowaniu podczas przysłaniania metody, jest dużym sygnałem błędnego modelowania rzeczywistości na klasy.
class Ssak
{
public override string ToString()
{
return "Jestem Ssakiem";
}
}

class Kot : Ssak
{
public override string ToString()
{
return "Jestem Kotem";
}
}

class Pies : Ssak
{
public override string ToString()
{
return "Jestem Psem";
}
}
Zasady użycia metod wirtualnych i metod nadpisanych
Istnieje pewna grupa zasad, które muszą być przestrzegane , aby mechanizm metod wirtualnych działał poprawnie.

Metody wirtualne i metody nadpisujące nie mogą być być prywatne.
Nazwy metody wirtualnej i nadpisującej muszą być takie same. Wielkość znaków się liczy.
Metoda wirtualna i metoda nadpisująca muszą mieć ten sam poziom dostępności. Czyli muszą mieć taki sam modyfikator dostępu.
Możesz nadpisać tylko metodę wirtualną.
Tak jak napisałem wcześniej, jeśli metoda nadpisująca nie ma słowa kluczowego override kompilator uznaje ,że chcesz przysłonić metodę, czyli stworzyć kompletnie inną implementacje.
Nie możesz zadeklarować równocześnie , że dana metoda jest wirtualna i równocześnie nadpisująca.
Jeśli chodzi o mechanizm dziedziczenia każda klasa dziedzicząca po klasie, która nadpisała metodę X może nadpisać ją jeszcze raz na swój sposób.
Refereowanie do klasy poprzez interfejs.
Jak pamiętamy obiekt można przypisać do zmiennej, która jest klasą bazową w stosunku do obiektu. W ten sam sposób możesz przypisać obiekt klasy do interfejsu.

Oto przykład , że obiekt pies może być przypisany do interfejsu “IRuchPoZiemi”

Pies pies = new Pies();
IRuchPoZiemi rpz = pies;
Zapis ten jest poprawny ponieważ pies dziedziczy po interfejsie IRuchPoZiemi. Tak jak z przypisaniem do klas bazowych, by przywrócić obiekt z interfejsu do swojej oryginalnej formy trzeba wykonać rzutowanie, bo w końcu obiekt przypisany do tego interfejsu niekoniecznie jest psem.

Mając obiekt przypisany do interfejsu można skorzystać tylko z metod udostępnianych przez interfejs.

Ten mechanizm jest użyteczny ponieważ możesz np. zadeklarować metodę, która w parametrach będzie potrzebowała tego interfejsu.

int MetodaBieganie(IRuchPoZiemi iruchpoziemi)
{
return iruchpoziemi.LiczbaNog();
}
Interfejsy - Explicite vs implicit
Podsumowując metody zaimplementowane Explicite są dostępne tylko wtedy, gdy przypiszemy je do interfejsu.

Oto parę istotnych informacji w pigułce na temat Explicite:

Nie używamy implementacji Explicite jako bariery bezpieczeństwa. Metoda ta wciąż może być użyta jeśli obiekt zostanie przypisany do interfejsu.
Używamy go wtedy, gdy chcemy ukryć implementacje metody.
Używamy go, gdy chcemy aby metoda zachowywała się jak prywatna.
Podobno pakowanie (boxing) zachodzi w czasie używania interfejsów Excplite dla typów wartościowych więc użycie go w takim wypadku zmniejsza sprawność kodu.
Stosujemy go, gdy istnieje konflikt nazw metod i chcemy je oddzielić zachowaniem.
klasy absrakcyjne
Klasy abstrakcyjne działają w podobny sposób jak interfejsy jednak ich metody mogą posiadać ciała i informacje. W klasie abstrakcyjnej możesz też zadeklarować metody wirtualne tak, aby klasa dziedzicząca po niej mogła podać swoją własną implementacje tej właśnie metody.

Klasy abstrakcyjne stosujemy zamiast interfejsów gdy kod się powiela.
Metody abstrakcyjna
Klasa abstrakcyjna może zawierać metody abstrakcyjne. Co to jest metoda abstrakcyjna?

Metoda abstrakcyjna działa w podobny sposób jak metoda wirtualna poza tym ,że nie posiada swojego ciała.

Klasa dziedzicząca musi implementować tę metodę jest to zasada zbliżona do interfejsów. W innym przypadku zobaczysz błąd w czasie kompilacji.
Metoda abstrakcyjna nie może być prywatna. Skoro klasa dziedzicząca musi implementować tę metodę to logicznie myśląc metoda nie może być prywatna ponieważ wtedy klasa dziedzicząca nie będzie miał do niej dostępu.

abstract class SsakZujacyTrawe : Ssak
{
public abstract void ZucieTrawy();
}
interface , virtual , override i sealed
Interface daje możliwość zadeklarowania samej nazwy metody i nic więcej.
Metoda wirtualna pokazuje domyślną implementacje metody, która może być nadpisana.
Słowo kluczowe override pozwala na nadpisanie metody wirtualnej.
Zamknięcie metody spowoduje zablokowanie dalszych modyfikacji metody dla klas dziedziczących.
interface.
Poniższy kod obrazuje tą kolejność.
IZucieTrway{
void ZucieTrawy();
}

abstract class SsakZujacyTrawe : Ssak,IZucieTrway
{
virtual public void ZucieTrawy(){}
}

class Krowa : SsakZujacyTrawe
{
sealed override public void ZucieTrawy() { }
}
class KrowaAfrykańska : Krowa
{

}
wirtualne właściwości
class Ssak
{
private int liczbanog;

public virtual int Liczbanog
{
get { return liczbanog; }
}

}

class Kot : Ssak
{
public override int Liczbanog
{
get { return 4; }
}
}
Jak widzisz to działa i właściwość może być nadpisana.

Występują też właściwości abstrakcyjnie ,ale tylko dla klas abstrakcyjnych.
Inicjowanie obiektów przy użyciu właściwości
Podobnie jak z tablicami możesz nadać właściwościom gotowe wartości w czasie inicjacji używając nawiasów klamrowych.



Jest to pewna alternatywa dla konstruktorów. Konstruktor mogą nie wypełniać wszystkich interesujących nas pól. Kiedy napiszesz taki kod kompilator uruchomi najpierw konstruktor ,a zaraz potem blok kodu SET dla każdej uzupełnionej w ten sposób właściwości.

CzasPracy czas = new CzasPracy() { Minuty=10,Sekundy=12 };
delegaty
Delegata jest wskaźnikiem do danej metody. Poprzez daną delegate możesz wywołać daną metodę. Kiedy wywołujesz daną delegatę program tak naprawdę wykonuje daną metodę, do której delegata się referowała.
lambda przykład
operacjeMatematyczne += (x => x*x);
//Proste wyrażenie które zwraca kwadrat swojego parametru
//Typ parametru x jest wnioskowany z kontekstu
//x można traktować jak zmienną pomocniczą
//nie może ona istnieć w innym miejscu w kodzie
operacjeMatematyczne += (x => { return x*x; });
//Wyrażenie które używa bloków z C#.
//Jest to już ciało niż proste wyrażenie
operacjeMatematyczne += ((int x) => x*x);

//proste wyrażenie które zwraca potęgę liczby x
//parametr x jest określony jawnie
MaszynaPracujaca mp = new MaszynaPracujaca();
MaszynaZadan mz2 = new MaszynaZadan();
mz2.Dodaj((() => mp.WylaczMaszyne(0)));
lambda
Wyrażenia lambda mogą zwracać wartości jednak muszą one pasować do typu danej delegaty, do której są dodawane.
Ciało wyrażenia lambda może być prostym wyrażeniem albo blokiem kodu C# z wieloma stwierdzeniami, wezwaniami innych metod, definicją zmiennych i innych rzeczy.
Zmienne zdefiniowane wewnątrz wyrażenia lambda istnieją tylko w tym bloku kodu i znikają gdy metoda się skończy,
Wyrażenie lambda ma dostęp do wszystkich zmiennych i metod znajdujących się po za tym wyrażeniem. W czasie wykonywania wyrażenia zmienne ulegają zmianie tymczasowo. Warto o tym pamiętać.
Jeśli wyrażenie lambda pobiera jakieś parametry możesz nie podawać ich typów ponieważ kompilator skojarzy je z kontekstu danego wyrażenia. Jednak przy słowach kluczowych jak ref i out musisz też podać ich typ.
Wyrażenie lambda może zmienić wartości na zawsze jeśli są one przesłane do metody za pomocą słów kluczowych ref i out.
Event
Zdarzenie może być zadeklarowane tylko w klasie i to ona jest zawsze źródłem tego zdarzenia.
Źródłem danego zdarzenia jest zazwyczaj klasa, która monitoruje dane środowisko oraz wywołuje zdarzenie w momencie spełnienia danego warunku.
Deklaracja zdarzenia jest podobna do deklaracji pola, jednakże ponieważ zdarzenia są przeznaczone dla delegat ich typem musi być delegata. No i oczywiście pojawia się tutaj kolejne słowo kluczowe “event”. Oto schemat deklaracji zdarzenia.

event NazwaTypuDelegaty NazwaZdarzenia
temp
temp