Dobrodružství v C#

Jak odkrýt zákoutí jazyka C#

Časová náročnost (min):

Začátečník

Pokročilý

Profesionál

Použitý operační systém : Hlavní vývojový nástroj :

Další vývojový software :

Jiný software :

Windows 2000 SP3

Visual C# .NET 2002

Visual Studio .NET 2002

Žádný

 

 

Obsah

Obtížnost

Čas (min)

 Předávání argumentů hodnotou a odkazem

* Vytváření přetížené metody

* Umístění uživatelského odkazu do okna Dynamic Help

 

 

Předávání argumentů hodnotou a odkazem

 

Úvodní tip bude patřit vysvětlení procesu předávání argumentů v jazyku C#. Ještě předtím, než se dostaneme k předávání argumentů hodnotou a odkazem, musíme si povědět pár slov k terminologii. Argumentem označujeme jakoukoliv platnou hodnotu, která bude předmětem předávání. Argumentem tak může být celé číslo, číslo s pohyblivou desetinnou čárkou, textový znak nebo řetězec. Argumentem může být dokonce také ukazatel na instanci jisté třídy. Aby bylo možné předávanou hodnotu (argument) přijmout v cílové funkci, musí tato funkce disponovat proměnnou, do které bude možné hodnotu uložit. Tato proměnná se nazývá formální parametr funkce.

 

Poznámka

V literatuře o programování se formální parametr funkce nazývá často zkráceně jenom jako parametr.

 

Funkce nemusí nutně pracovat pouze s jedním parametrem, právě naopak, formálních parametrů může být i několik. Zvyčejně však platí pravidlo, že funkce má tolik formálních parametrů, kolik vstupních hodnot očekává. Jestliže víte, že funkce bude vždy pracovat pouze s jednou celočíselnou hodnotou, stačí, když budete deklarovat jenom jeden formální parametr.

 

Varování

Je velmi důležité, abyste si zapamatovali rozdíl mezi argumentem a formálním parametrem. Argument představuje hodnotu, která je předávána cílové, resp. volané funkci. Kontejner, do kterého je argument uložen, se nazývá formální parametr. Přestože je tento rozdíl mezi argumenty a formálními parametry zřetelný, mnoho autorů knih o programování si oba termíny neustále plete a velice často dochází taktéž k vzájemnému zaměňování těchto pojmů. 

 

C#, podobně jako i další programovací jazyky platformy .NET, podporuje dva typy předávání argumentů: předávání argumentů hodnotou a odkazem. Rozdíl mezi uvedenými typy předávání argumentů si vysvětlíme na následujících řádcích.

 

Při předávání argumentu hodnotou je volané, resp. cílové funkci odevzdána kopie původního argumentu. To znamená, že cílová funkce obdrží kopii argumentu a nikoliv skutečný argument. Proces předávání argumentu hodnotou je znázorněn na obr. 1.

 

 

Obr. 1 – Předávání argumentu hodnotou

 

Při předávání argumentu hodnotou musí procesor vykonat dodatečnou práci, protože je zapotřebí původní argument podrobit kopírovacímu procesu. Formální parametr volané funkce obdrží kopii skutečného argumentu, přičemž v těle funkce je následně použita právě tato kopie. Funkce může použít dodanou kopii argumentu v různých výrazech a také může s touto kopii provádět jakékoliv platné programovací operace. Při těchto operacích může dojít ke změně hodnoty kopie argumentu, ovšem tato změna nijak neovlivní původní argument ve volající funkci (ani nemůže, protože v těle funkce pracujeme s kopii původního argumentu a nikoliv se skutečnou podobou argumentu). Je-li argument předáván hodnotou, nikdy nemůže dojít k jeho změně – změnit se může jenom kopie argumentu, která je poskytnuta cílové funkci (ovšem tato změna je pouze dočasná, jelikož životní cyklus formálního parametru cílové funkce je ohraničen samotnou životností této funkce).

 

Varování

Platforma .NET Framework povýšila předáváni argumentů hodnotou na implicitní způsob předávání argumentů. To tedy znamená, že jestliže není výslovně určeno jinak, budou všechny argumenty předávány hodnotou. Řečeno jinými slovy, vždy budou vytvořené kopie skutečných argumentů a teprve tyto budou předány volaným funkcím.

 

Naproti tomu, při předávání argumentu odkazem je volané funkci předána skutečná hodnota, tedy skutečný argument. Cílová funkce tak pracuje s původním argumentem a je-li tento původní argument změněn, tato změna se projeví také ve volající funkci. Grafickou interpretaci předávání argumentu odkazem přináší obr. 2.

 

 

Obr. 2 – Předávání argumentu odkazem

 

Předveďme si nyní ukázku předávání argumentu hodnotou i odkazem v jednom fragmentu programového kódu:

 

            private void button1_Click(object sender, System.EventArgs e)

            {

                  //Deklarace proměnných a a b typu int.

                  int a, b;

                 

                  //Vícenásobné přiřazení hodnoty 10 do proměnných a a b.

                  a = b = 10;

                 

                  //Zavolání první funkce. Funkci je předána hodnota

                  //proměnné a (jde o předání argumentu hodnotou).

                  CílováFunkce1(a);

                 

                  //Aktivace druhé funkce. Funkci je předána hodnota

                  //proměnné b (jde o předání argumentu odkazem). Protože je

                  //hodnota proměnné b předávána odkazem, musí být před jméno

                  //proměnné umístěno klíčové slovo ref.

                  CílováFunkce2(ref b);

                 

                  //Deklarace referenční proměnné txtBox1, vytvoření instance

                  //třídy TextBox a umístění odkazu na vniklou instanci do

                  //referenční proměnné. Vytváříme tedy nové textové pole.

                  TextBox txtBox1 = new TextBox();

 

                  //Přidání vytvořené instance třídy TextBox na formulář.

                  this.Controls.Add(txtBox1);

 

                  //Určení velikosti instance třídy TextBox.

                  txtBox1.Size = new Size(200, 150);

 

                  //Určení pozice instance třídy TextBox.

                  txtBox1.Location = new Point(10, 10);

 

                  //Text, jenž se objeví v textovém poli.

                  txtBox1.Text = "Proměnná a: " + a + " Proměnná b: " + b;

            }

           

            //Definice první funkce.

            private void CílováFunkce1(int FormálníParametr1)

            {

                  //Modifikace kopie původního argumentu.

                  FormálníParametr1 = FormálníParametr1 * 2;

            }

 

            //Definice druhé funkce. Všimněte si, že před určením datového typu

            //formálního parametru se nachází klíčové slovo ref.

            private void CílováFunkce2(ref int FormálníParametr2)

            {

                  //Modifikace původního argumentu.

                  FormálníParametr2 = 10 * FormálníParametr2 % 6;

            }

 

V úloze volající funkce vystupuje zpracovatel události Click tlačítka button1. V těle volající funkce jsou deklarovány dvě proměnné (a, b), které jsou vzápětí nabídnuty cílovým funkcím. Mějte na paměti, že při předávání argumentů hodnotou nemusíte používat žádné dodatečné programovací elementy, protože tato varianta předávání argumentů je implicitní. Na druhé straně, při předávání argumentů odkazem je zapotřebí použít klíčové slovo ref, které naznačuje, že chcete použít právě tento způsob předávání argumentů. Klíčové slovo ref se musí vyskytovat na dvou místech:

 

 

            CílováFunkce2(ref b);

 

 

 

            private void CílováFunkce2(ref int FormálníParametr2)

            {

                  //Modifikace původního argumentu.

                  FormálníParametr2 = 10 * FormálníParametr2 % 6;

            }

 

Přeložíte-li dříve uvedený kód prostřednictvím kompilátoru, uvidíte, že po zavolání obou funkcí bude hodnota proměnné a nezměněna (10), zatímco hodnota proměnné b bude zcela jiná (4).

 

Poznámka

A jak jsme dospěli k hodnotě modifikované podobě proměnné b? Hodnotu proměnné b vypočítává tento řádek zdrojového kódu:

 

FormálníParametr2 = 10 * FormálníParametr2 % 6;

 

 Algoritmus výpočtu nové hodnoty proměnné b má přibližně tuto podobu:

 

1.      Původní hodnota proměnné b (10) je vynásobena číslem 10. Výsledkem součinu je tedy hodnota 100.

2.      Na hodnotu, jež vzešla ze součinu, je aplikován operátor modulus (%). Operátor modulus vrací zbytek po celočíselném dělení. Jelikož 100 / 6 = 16, zbytek po celočíselném dělení je 4 (100 – (16 * 6) = 100 – 96 = 4).

 

 

Vytváření přetížené metody

 

Při programování se velice často stává, že potřebujete vytvořit metodu s jedním názvem, ovšem chcete, aby se metoda chovala při různých příležitostech různě. Například budete chtít naprogramovat metodu ZačítKreslit, ale budete chtít, aby metoda někdy nakreslila obdélník a jindy zase elipsu, či nějaký jiný komplexní geometrický útvar. V této situaci vám přijde vhod technika, které se říká přetížení metody. Přetížit metodu znamená vytvořit další variantu metody, přičemž tato nová varianta bude mít stejný název jako metoda původní, ovšem lišit se bude seznamem svých parametrů.

 

Varování

Modifikací původní metody můžete vytvořit kolik chcete, ovšem musíte pamatovat na skutečnost, že:

 

a)      Všechny varianty metody musí mít stejný název jako originální metoda.

b)      Všechny varianty metody se musí odlišovat svou signaturou, tedy seznamem parametrů.

c)       Modifikátory přístupu a návratové hodnoty nových variant metody se mohou od svých původních protějšků lišit, ale také mohou zůstat stejné.

  

Budete-li chtít vytvořit přetíženou metodu, postupujte podle následujících kroků:

 

  1. Spusťte Visual C# .NET a vytvořte standardní aplikaci pro Windows (Windows Application).
  2. Do projektu přidejte soubor s kódem třídy (Project à Add Class).
  3. Kód, jenž se nachází v souboru s kódem třídy, upravte podle následujícího vzoru:

 

//Import důležitých jmenných prostorů.

using System;

using System.Drawing;

using System.Windows.Forms;

 

//Deklarace jmenného prostoru, v němž je uložena třída A.

namespace PřetíženáMetoda

{

      /// <summary>

      /// Třída ukazuje použití přetížené metody.

      /// </summary>

      public class A

      {

            //Konstruktor třídy A.

            public A()

            {

                 

            }

 

            //Definice první varianty přetížené metody ZačítKreslit.

            public void ZačítKreslit(int PoziceX, int PoziceY,

                  int Šířka, int Výška, bool KreslitVýplň)

            {

                  //Deklarace odkazové proměnné frm a uložení ukazatele na

                  //aktuální instanci třídy Form do této proměnné.

                  Form frm = Form.ActiveForm;

 

                  //Vytvoření instance třídy Rectangle a určení pozice

                  //a velikosti vytvořené instance.

                  Rectangle obd = new Rectangle(new Point(PoziceX, PoziceY),

                        new Size(Šířka, Výška));

                 

                  //Vytvoření grafického pera, neboli instance třídy Pen.

                  //Je výslovně určeno, že grafické pero má mít červenou barvu

                  //a tloušťku 4 jednotky.

                  Pen p = new Pen(Color.Red, 4.0F);

 

                  //Vytvoření grafického štětce (instance třídy SolidBrush),

                  //jenž má oranžovou barvu.

                  Brush b = new SolidBrush(Color.Orange);

 

                  //Vytvoření grafického objektu pomocí metody CreateGraphics.

                  Graphics g = frm.CreateGraphics();

 

                  //Metoda DrawRectangle má na starosti nakreslení obdélníku.

                  g.DrawRectangle(p, obd);

                 

                  //Jestliže je doručen požadavek na vykreslení výplně

                  //obdélníku, bude zavolána metoda FillRectangle,

                  //která vyplní vnitřní plochu obdélníku oranžovou barvou.

                  if (KreslitVýplň)

                        g.FillRectangle(b, obd);

 

                  //Po skončení prací dochází k uvolnění paměťových zdrojů,

                  //které byly alokované grafickými objekty.

                  g.Dispose();

                  b.Dispose();

                  p.Dispose();

            }

     

            //Definice druhé varianty přetížené metody. Na rozdíl od první

            //verze přetížené metody, tato metoda umožňuje uživateli

            //nastavit také barvu výplně pro nakreslený obdélník.

            public void ZačítKreslit(int PoziceX, int PoziceY,

                  int Šířka, int Výška, bool KreslitVýplň, Color BarvaVýplně)

            {

                  //Deklarace odkazové proměnné frm a uložení ukazatele na

                  //aktuální instanci třídy Form do této proměnné.

                  Form frm = Form.ActiveForm;

 

                  //Vytvoření instance třídy Rectangle a určení pozice

                  //a velikosti vytvořené instance.

                  Rectangle obd = new Rectangle(new Point(PoziceX, PoziceY),

                        new Size(Šířka, Výška));

 

                  //Deklarace referenční proměnné, do které bude možné

                  //uložit odkaz na instanci třídy SolidBrush.

                  Brush b;

                 

                  //Vytvoření grafického pera, neboli instance třídy Pen.

                  //Je výslovně určeno, že grafické pero má mít červenou

                  //barvu a tloušťku 4 jednotky.

                  Pen p = new Pen(Color.Red, 4.0F);

                 

                  //Jestliže je formální parametr BarvaVýplně prázdný

                  //(IsEmpty), je generována výjimka, která říká,

                  //že BarvaVýplně nebyla inicializována. V opačném případě

                  //je vytvořena instance třídy SolidBrush, přičemž

                  //konstruktoru třídy je předána hodnota formálního

                  //parametru BarvaVýplně.

                  if (BarvaVýplně.IsEmpty)

                        throw new

                             Exception("BarvaVýplně nebyla inicializována.");

                  else

                        b = new SolidBrush(BarvaVýplně);

                 

                  //Vytvoření grafického objektu pomocí metody CreateGraphics.

                  Graphics g = frm.CreateGraphics();

                 

                  //Metoda DrawRectangle má na starosti nakreslení obdélníku.

                  g.DrawRectangle(p, obd);

                 

                  //Jestliže je doručen požadavek na vykreslení výplně

                  //obdélníku, bude zavolána metoda FillRectangle,

                  //která vyplní vnitřní plochu obdélníku oranžovou barvou.

                  if (KreslitVýplň)

                        g.FillRectangle(b, obd);

                 

                  //Po skončení prací dochází k uvolnění paměťových zdrojů,

                  //které byly alokované grafickými objekty.

                  g.Dispose();

                  b.Dispose();

                  p.Dispose();

            }

 

      }

}

 

  1. Na formulář přidejte instanci ovládacího prvku Button a do její událostní procedury Click zadejte programový kód pro vytvoření instance třídy A.

 

            PřetíženáMetoda.A objekt = new PřetíženáMetoda.A();

 

  1. Dále zadejte název instance (objekt), tečku a ze seznamu dostupných metod vyberte metodu ZačítKreslit. Všimněte si, že ihned jak zadáte otevírací závorku za jménem metody, technologie IntelliSense vám nabídne bublinovou nápovědu se seznamem variant přetížené metody (obr. 3).

 

 

Obr. 3 – Technologie IntelliSense a první varianta přetížené metody

 

V levé části okna s bublinovou nápovědou se nacházejí malé šipky (a ), pomocí kterých si můžete prohlížet všechny alternativy přetížené metody. Jestliže klepnete na druhou šipku (), uvidíte další dostupnou variantu metody ZačítKreslit (obr. 4).

 

 

Obr. 4 – Technologie IntelliSense a druhá varianta přetížené metody

 

Tip

Pokud si chcete prohlédnout jednotlivé verze přetížené metody, nemusíte nutně klepat na tlačítka se šipkami. Stejný účinek totiž dosáhnete také použitím kurzorových kláves na klávesnici.

 

  1. Přetížená verze metody ZačítKreslit vám umožňuje určit barvu výplně. Budete-li chtít nakreslit obdélník s oranžovou výplní, zavolejte metodu v této podobě:

 

            objekt.ZačítKreslit(20, 30, 200, 100, true, Color.Orange);

 

 

Umístění uživatelského odkazu do okna Dynamic Help

 

Integrované prostředí Visual Studia .NET s sebou přineslo novou dimenzi přístupu k informačním zdrojům. Veškeré akce programátora jsou pečlivě kontrolovány a na základě stylu práce programátora se v okně Dynamic Help zobrazují odkazy na témata, o kterých si Visual Studio .NET myslí, že by mohla být pro vývojáře užitečná. Ačkoliv je technologie, na základě které pracuje interaktivní vyhledávání informací, značně komplikovaná, dozvíte se, jak přidat svůj vlastní odkaz do okna Dynamic Help, a to prostřednictvím správně nakonfigurovaného XML souboru.

 

Poznámka

Kromě použití XML souboru existuje ještě jeden způsob, jak do okna Dynamic Help umístit odkazy na vlastní témata. V tomto případě je nutné vytvořit kompilovaný soubor nápovědy nové generace s názvem MS Help 2.0. Kompilovaný soubor má extenzi HxS a lze jej vytvořit ve speciálním softwaru s názvem Help Workshop (tento software je součástí kolekce Visual Studio .NET Help Integration Kit, VSHIK).

 

Postupujte následovně:

 

  1. Spusťte Visual Studio .NET a vytvořte nový XML soubor (FileàNewàFile).
  2. Obsah XML souboru upravte následovně:

 

<?xml version="1.0" encoding="utf-8" ?>

<DynamicHelp xmlns="http://msdn.microsoft.com/vsdata/xsd/vsdh.xsd"

xmlns:xsi="http://www.w3.org/2000/10/XMLSchema-instance"

xsi:schemaLocation="http://msdn.microsoft.com/vsdata/xsd/vsdh.xsd">

   <Context>

      <Keywords>

         <KItem Name="VS.SolutionExplorer"/>

      </Keywords>

      <Links>

        <LItem URL="http://www.MojeWebStranka.cz"

        LinkGroup="Samples">Otevrit internetovy prohlizec</LItem>

      </Links>

   </Context>

</DynamicHelp>

 

Tip

Pokud budete chtít zkopírovat uvedený XML kód do souboru, jenž máte otevřený ve Visual Studiu .NET, při vkládání kódu ze schránky použijte příkaz Paste as HTML z nabídky Edit. Jestliže byste totiž použili jednoduchý příkaz Paste, nebyl by XML kód správně vložen do cílového souboru.

 

XML soubor používá několik specifických značek, které je pro zobrazení odkazu v okně Dynamic Help nutné implementovat. Značkou nejvyšší úrovně je DynamicHelp, která slouží pro určení odkazu na XSD soubor s názvem vsdh. Referenci na soubor vsdh.xsd je potřebné zařadit, protože jinak by náš odkaz nebyl funkční. Každé téma, na které se chcete odkázat, je reprezentováno značkou Context. Značka Context obsahuje dvě vnořené značky: Keywords a Links. Značka Keywords obsahuje vnořenou značku KItem, která deklaruje klíčové slovo (atribut Name). Toto klíčové slovo představuje jistou programovou entitu ve Visual Studiu. NET. V našem případě je touto entitou okno Solution Explorer, což znamená, že bude-li toto okno aktivní, v okně Dynamic Help se zobrazí náš odkaz. Podrobnosti týkající se odkazu jsou determinovány ve značce LItem (tato značka je vnořenou značkou značky Links). Značka LItem obsahuje značný počet atributů, ovšem pro nás jsou důležité zejména dva z nich: URL a LinkGroup. Atribut URL definuje cílový objekt, na který bude odkaz nasměrován. Tímto objektem může být webová stránka na vzdálené počítačové stanici, nebo HTML dokument na lokálním PC. Atribut LinkGroup určuje skupinu odkazů, do které bude náš odkaz zařazen. V naší ukázce bude odkaz uložen do skupiny, resp. sekce Samples okna Dynamic Help.   

 

  1. Uložte XML soubor do adresáře \Visual Studio .NET\Common7\IDE\HTML\XMLLinks\1033.
  2. Zavřete Visual Studio .NET a opětovně jej spusťte.
  3. Klepněte na dialogové okno Solution Explorer a podívejte se do okna Dynamic Help. V sekci Samples by se měla objevit nová položka Otevrit internetovy prohlizec (obr. 5).

 

 

Obr. 5 – Uživatelský odkaz v dialogovém okně Dynamic Help

 

Klepnete-li na tuto položku, Visual Studio .NET se pokusí otevřít specifikovanou webovou stránku v interním prohlížeči.

 

 

Ján Hanák