|
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
Ú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ů:
//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();
}
}
}
PřetíženáMetoda.A objekt = new PřetíženáMetoda.A();
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. |
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ě:
<?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.
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