Skip to main content.

Link

On the address http://li153-236.members.linode.com/tutorials/csharp/ you can read very good tutorial to C# language. If you already know some object oriented language (like Java or C++), this is ideal solution for you. In very brief and well-aranged form in a short time you will learn all features of C# language. The Tutorial is oriented only to the language, it does not describe .Net library. If you want to learn .Net library, the best way is to read MSDN and if you know the language, you can immediately use all functions.

I have read few books about C#, concretely:

All are interesting but you will not learn more about C# language than in this tutorial. Of course, there are few additional informations. And I have written these additional informations for myself. If you do not want to read all these books, although I recommend them to you, read at least this tutorial and my supplemental notes and you will know C# language basically equally.

  ^ 

My supplemental Notes

Sorry, in Czech language only.

* Visual Studio
  + umí otevřít binární soubor a má moc pěkný editor binárních souborů - možnost hexa editace, nebo přímo
    editace bytů, vkládání, mazání, schránka atd.

* komentáře - dokumentace
  + html dokumentace ke solution se vytvoří z menu Tools, Build Comment Web Pages...,
    zaškrtnout Build for entire Solution a odškrtnout For security, display HTML in comments as text
  + html dokumentace využívá komentářů označených ///
  + pokud nad čímkoliv, co chceme zdokumentovat, napíšeme '///', tak VS.Net automaticky vygeneruje
    celou XML strukturu za nás

* pojmenovávání identifikátorů - velikost písmen
  + podrobně viz například "C Sharp In A Nutshell", kapitola 22, oddíl III
  + základní pravidlo je to, že co je public, má začínat velkým písmenem. Private složky a lokální proměnné
    začínají malým písmenem, stejně jako parametry metod.
    Další písmena ve slově jsou vždy malá a pokud se jedná o složeninu více slov,
    každé další slovo začíná velkým písmenem. Třídy, struktury a delagates začínají také velkým písmenem.
    Názvy interfaců začínají také velkým a mají předponu I a končí na 'able', pokud je to anglicky.
    Konstanty se mohou psát všechny velkými písmeny (například PI). Neměla by se používat podtržítka.

    Ale rozhodně by se v žádném případě neměly dvě public položky lišit pouze velikostí písmen (z důvodu
    .Net kompatibility např. s Visual Basicem, který nerozlišuje velikosti písmen). Naopak velice dobrým
    a často používaným zvykem je označovat shodně (a odlišovat pouze velikostí počátečního písmena) související
    věci (například privátní proměnnou s malým a příslušnou property s velkým počátečním písmenem).
* metoda Main
  + více tříd v programu může obsahovat metodu Main.
  + která se má spustit, se řekne překladači takto:
    csc /main:<jméno_třídy s hlavní Main>
  + je to užitečné pro ladění, kdy pro každou třídu můžeme udělat malý testovací program
  + jde to nastavit i ve vlastnostech projektu ve Visual Studiu

* předdefinované value-types (int, float atd...)
  + jsou ve skutečnosti struktury
  + k dispozici jsou statické konstanty a metody, např:
    int.MaxValue, int.MinValue, int.Parse(string s) - převede řetězec na int
  + pro konkrétní proměnné daného typu jsou k dispozici různé metody, například .ToString()
  + toto lze použít i na číselné hodnoty, například (2).ToString()

* decimal
  + super desetinný typ, ve kterém narozdíl od double a float platí, že 3.14m * 5m == 15.7m
  + pokud chci říct, že konstanta má být typu decimal, napíšu za číslo písmenko M nebo m,
    např. decimal a = 3.14m;

* checked
  + pokud chceme zapnout checked režim pro celý program, dáme překladači csc parametr /checked+

* pole
  + jsou referenční typ
  + vhledem k tomu, že se pole alokuje dynamicky za běhu programu, nemusí být velikost pole konstanta již během překladu,
    stejně tak jeho inicializátory. Tento zápis je proto možný:

    double[] pole = {1.5, 3.1};
       ...
    Random r = new Random();
    pole = new double[] {r.NextDouble(), r.NextDouble(), r.NextDouble()};
* object
  + všechny objekty jsou z object zděděné
  + pokud do object uložíme referenci na objekt některé konkrétní třídy, můžeme její název zjistit pomocí
    .GetType().ToString()
  + v .GetType() je k dispozici mnoho dalších zajímavých informací o objektu (názvy metod, vlastností atd.)
  + pomocí operátoru 'výraz is typ' se dá zjistit, jestli je výraz daného typu.
    Aby výsledek operátoru 'is' byl 'true', výraz nesmí být null a musí jít explicitně přetypovat na daný typ.

* Modifikátory přístupových práv
  + třída nevnořená:            implicitně internal, jinak může být pouze internal nebo public
  + složky třídy:               implicitně jsou private (včetně vnořených tříd a metod)
  + enumerators a interface:    složky jsou public

* implicitní hodnoty proměnných
  + lokální proměnné (tedy proměnné definované v těle metody statické i nestatické)
    mají hodnotu náhodnou, ale překladač nám naštěstí nedovolí takovouto neinicializovanou
    proměnnou používat
  + proměnné třídy (ať už statické proměnné nebo nestatické) jsou defaultně 0, null, false atd.
  + pole mají všechny prvky nulové (zařizuje to implicitní konstruktor pole)
* const a readonly
  + hodnota const musí být dána již během překladu (konkrétní číslo)
  + hodnota readonly se může v konstruktoru vypočítat z jiných proměnných,
    jinde už se ale také nesmí změnit

* this & base
  sice se o těchto dvou referencích tutoriál zmiňuje, ale ne moc výrazně
  + this je reference na tento objekt
  + base je reference na rodičovskou třídu (při dědění)
    - užitečné např. při volání rodičovského konstruktoru nebo při odkazování na různé zastíněné metody

* dědění
  + konstruktor zděděné třídy musí volat konstruktor nadřazené třídy, například takto:
    public Ctverec(int strana) : base(strana, strana)  { ... }  // zavolá konstruktor Obdélníku
  + pokud ve zděděné třídě nezavoláme konstruktor, překladač automaticky volá defaultní konstruktor base třídy,
    ale pozor: třída object má default konstruktor, ale některé třídy ho mít nemusí a v takovém případě nepůjde
    program přeložit.

* interfaces
  + jsou pořádně vysvětleny v knize "Microsoft Visual C# .NET Step by Step 2003", v kapitole 12, oddíl II
  + interface může obsahovat jak metody, tak ale i properties a indexers - viz stejná kniha, kapitoly 14 a 15

* výjimky
  + pokud do těla catch napíšeme 'throw;', tak bude výjimka předána dál, jako kdyby nebyla ošetřena
* příkaz using - šikovné například pro práci se soubory - i v případě výjimky vždy uvolní alokovaný zdroj
  + 'using (type variable = initialization)  embeddedStatement'

    znamená toto:

    {
       type variable = initialization;
       try
       {
           embeddedStatement
       }
       finally
       {
           if (variable != null)
           {
               ((IDisposable)variable).Dispose();
           }
       }
    }

  + třída 'type' musí implementovat interface IDisposable (a tedy funkci Dispose())
  + více viz "Microsoft Visual C# .NET Step by Step 2003", kapitola 13, oddíl II
  + příklad použití:
    try {
        using (TextReader reader = new StreamReader(@"C:\WINDOWS\system.ini")) {
            Console.WriteLine(reader.ReadLine());   // vypíše první řádku souboru
        }
    }
    catch (Exception e) {
        Console.WriteLine(e.Message);
    }
* delegates a events
  ? Jaký je rozdíl mezi delegates a events?
  + Events mají mnohem více limitovaný přístup než delegates. Když je event definována public,
    kód z jiných tříd může jenom přidávat nebo ubírat handlery této event. Nemůže omylem
    smazat handler, o kterém neví, zjistit všechny handlery nebo zrušit všechny handlery.
    Events také umožňují větší flexibilitu v podmínkách, jak jsou handlery uloženy.
    Events jsou tedy bezpečnější pro vytváření rozhraní třídy, delegates se používají pro realizaci events.

    Princip je takový, že vně třídy deklarujeme např. 'delegate void Funkce();' a uvnitř třídy uděláme např.
    'public event Funkce SeznamFunkci;' Kdokoliv pak může provádět
    'Třída.SeznamFunkci += new Funkce(MojeTřída.MojeFunkce());',
    případně použít '-=' pro odebrání ze seznamu, ale nemůže udělat např. 'SeznamFunkci = null',
    což by ale šlo, pokud by v deklaraci SeznamFunkci nebylo uvedeno slovo 'event'. To je tedy ten rozdíl mezi
    delegates a events - events mají limitovanější možnosti, tudíž jsou bezpečnější.

    Pokud pak chceme zavolat všechny funkce ze 'SeznamFunkci', je nutné nejdřív otestovat, zda seznam není prázdný,
    protože jinak by to vyhodilo výjimku. Je jedno, zda jsme použili klíčové slovo 'event' nebo ne. Např:

    if (SeznamFunkci != null)  SeznamFunkci();


* přetěžování operátorů
  + viz "Microsoft Visual C# .NET Step by Step 2003", kapitola 17, oddíl III
* problém s odkazováním objektů mezi jednotlivými formuláři

 "Mám jedno hlavní okno, k tomu jedno modální a tlačítkem na tom modálním okně chci spustit metodu,
  která upravuje vzhled toho hlavního okna. Problém je, že se mi ty jednotlivý metody ani proměnný nevidí..."

class Form1 : System.Windows.Forms.Form {
    public Label label1 = new Label();
    .
    .
    .

    public static void Main() {
        JinaTrida jinaTrida = new JinaTrida(this);  // předání dceřinnému objektu odkaz na rodiče
        jinaTrida.ShowModal();  // zobrazení modálního okna
    }
}

class JinaTrida : System.Windows.Forms.Form {
    Form1 formular;        // pro uložení odkazu na rodičovský formulář

    public JinaTrida(Form1 formular) {
        this.formular = formular;   // uložení odkazu
    }

    public void TlacitkoStisknuto() {
        formular.label1.Text = "Ahoj";  // změna vlastnosti v rodičovském formuláři
    }
}
* internetový odkaz

linkLabel1_LinkClicked(object sender, System.Windows.Forms.LinkLabelLinkClickedEventArgs e) {
    // spuštění externího procesu - provede se dle registrovaných přípon
    System.Diagnostics.Process.Start("mailto:borilt@gmail.com");
    linkLabel1.LinkVisited=true;
}

  ^ 

Version

This version of my supplemental notes is 18/12/2005.