Modul9, Courseware Development Tools


Przesyłanie argumentów do metody

0x08 graphic
Przegląd zagadnień

W celu umożliwienia metodzie wykonywanie działania dla różnych wartości i parametrów oraz przekazania wielu wartości przez metodę możemy przekazać metodzie odpowiednie argumenty. Przy pomocy argumentów metody, lub inaczej parametrów metody, tworzymy interfejs, przy pomocy którego metoda wymienia informację (dane) z pozostałymi częściami programu. W poprzednim rozdziale do wymiany informacji między metodami były używane zmienne współdzielone, w innych językach natomiast można używać tzw. zmiennych globalnych - zmiennych zadeklarowanych poza metodą i poza klasą. Wymiana informacji między metodami z użyciem zmiennych współdzielonych w porównaniu do przesyłania argumentów do metody, generuje mniej czytelny kod. Sam mechanizm przesyłania argumentów do metody wymusza na programiście nadanie odpowiednich wartości parametrom, od których jest zależne działanie metody. Dzięki temu można uniknąć licznych błędów logicznych. Poszczególne metody stają się niezależnymi jednostkami.

Po skończeniu tego rozdziału studenci będą potrafić:

0x08 graphic
Deklaracja i wywołanie metod z parametrami

Listę parametrów które mają być przekazane do metody, umieszczamy wewnątrz nawiasów okrągłych tuż za nazwą metody. Każdy parametr musi mieć określony typ i nazwę. Również gdy kilka parametrów ma ten sam typ, każdemu argumentowi trzeba oddzielnie określić typ. Poszczególne parametry oddzielamy przecinkiem. Wszystkie argumenty zdefiniowane wewnątrz nawiasów okrągłych nazywamy parametrami formalnymi metody. Nazwy parametrów są lokalne dla danej metody i są dostępne w całym "ciele" metody.
Następujące przykłady pokazują jak definiować metodę z parametrami:

  1. Metoda przyjmująca dwa argumenty typu string

    static void Powitanie(string imie, string nazwisko)
    {
    Console.WriteLine("Witam Pana(ią) {0} {1}",
    imie, nazwisko);
    }

  2. Metoda przyjmująca jeden parametr typu double

    static double Szescian(double x)
    {
    return x*x*x;
    }

Wywołując metodę z parametrami, każdemu jej argumentowi musimy dostarczyć wartość odpowiedniego typu. Wartości te umieszczamy w nawiasach okrągłych po nazwie metody i są one przypisywane argumentom na podstawie kolejności występowania. Poszczególne wartości oddzielamy przecinkiem. I tak, aby wywołać metodę Powitanie z przykładu powyżej należy napisać:

Powitanie("Kubuś", "Puchatek");

Argumentowi o nazwie imie zostanie nadana wartość Kubuś, a argumentowi nazwisko wartość Puchatek. Wykonanie powyższej linijki spowoduje pojawienie się na ekranie napisu:

Witam Pana(ią) Kubuś Puchatek

Argumenty (wartości, zmienne) umieszczone w nawiasach okrągłych w miejscu wywołania metody nazywamy parametrami aktualnymi metody.

0x08 graphic
Sposoby przesyłania argumentów do metody

W języku C# mamy trzy sposoby przesyłania argumentów do metody:

Przesyłanie parametru przez wartość.

Przesyłanie przez wartość jest domyślnym mechanizmem przesyłania argumentów do metody. Argument jest traktowany jako parametr wejściowy. Przesyłanie przez wartość definiujemy przez podanie typu argumentu i jego nazwy, czyli tak jak to było pokazane wcześniej w tym rozdziale. W miejscu wywołania metody, każdy parametr formalny przesyłany przez wartość reprezentuje nowo utworzoną zmienną lokalną. Zmienne te inicjalizowane są wartościami odpowiednich parametrów aktualnych.
Mechanizm przesyłania przez wartość charakteryzuje się następującymi właściwościami:

Przesyłanie parametru przez referencję.

Argument przesyłany przez referencję traktowany jest, zarówno jako parametr wejściowy jak i parametr wyjściowy. Przesyłanie przez referencję definiujemy przez dodanie przed nazwą typu parametru słowa ref, dla każdego argumentu przesyłanego przez referencję.

static void PrzezReferencje(ref int x,ref int y){...}

W miejscu wywołania metody, dla parametrów przesyłanych przez referencję, nie jest tworzona nowa zmienna. Parametr formalny reprezentuje ten sam obszar pamięci, tą samą zmienną, co parametr aktualny. W celu wywołania metody, przed każdym argumentem przesyłanym przez referencję musimy postawić słowa ref.

PrzezReferencje(ref akt1,ref akt2);

Przy powyższym wywołaniu, zmienna akt1 wewnątrz metody PrzezReferencje będzie się nazywać ("będziemy przezywać") x, a zmienna akt2 będzie się nazywać y.
Mechanizm przesyłania przez referencję charakteryzuje się następującymi właściwościami:

Przesyłanie parametru jako parametr wyjściowy.

Argument przesyłany jako parametr wyjściowy traktowany jest jako parametr wyjściowy. Przesyłanie argumentu jako parametr wyjściowy definiujemy przez dodanie przed nazwą typu parametru słowa out, dla każdego argumentu przesyłanego jako parametr wyjściowy.

static void JakoWyjsciowy(out int x,out int y){...}

W miejscu wywołania metody, dla parametrów przesyłanych jako parametr wyjściowy, podobnie jak w przypadku parametrów przesyłanych przez referencję, nie jest tworzona nowa zmienna. Parametr formalny reprezentuje ten sam obszar pamięci, tą samą zmienną, co parametr aktualny. W celu wywołania metody, przed każdym argumentem przesyłanym jako parametr wyjściowy musimy postawić słowa out.

JakoWyjsciowy(out akt1,out akt2);

Przy powyższym wywołaniu, zmienna akt1 wewnątrz metody JakoWyjsciowy będzie się nazywać ("będziemy przezywać") x, a zmienna akt2 będzie się nazywać y.
Mechanizm przesyłania argumentu jako parametr wyjściowy charakteryzuje się następującymi właściwościami:

Przykłady demonstrujące różne sposoby przesyłania argumentów do metody można znaleźć w programach RodzajePrzesylan i RownanieKwadratowe, które stanowią część rozwiązania Kurs\Demo\Modul9\Modul9.sln, gdzie Kurs jest katalogiem, gdzie skopiowano pliki kursu.

0x08 graphic
Argumenty typów referencyjnych

Przesyłanie argumentu przez wartość powoduje utworzenie nowej zmiennej i skopiowanie zawartości parametru aktualnego do tej zmiennej. W przypadku przesłania zmiennej typu referencyjnego spowoduje to, że nowo utworzona zmienna będzie się odwoływać do tego samego obiektu, co zmienna która została przesłana jako parametr aktualny. Zmiany obiektu wewnątrz metody przy pomocy nowo utworzonej zmiennej, będą widoczne również na zewnątrz metody. Rozważmy to na przykładzie przesyłania tablic do metody - tablice są obiektami, typem referencyjnym.

static void M1(int [] t)
{
t[0] = 1;
}

...
int [] tab = {10,11,12};
M1(tab);
Console.Write(tab[0]);

W wyniku działania powyższego kodu na ekranie powinno pojawić się:

1

Dzieje się tak, ponieważ zmienna tablicowa t oraz zmienna tablicowa tab odwołują się do tego samego obiektu.

Rozważmy jeszcze jeden przykład:

static void M2(int [] t)
{
t = new int[3];
t[0] = 1
}


...
int [] tab = {10,11,12};
M2(tab);
Console.Write(tab[0]);

W wyniku działania powyższego kodu na ekranie powinno pojawić się:

10

Przykład powyższy różni się tym od poprzedniego, że w momencie ustawiania wartości pierwszego elementu tablicy w metodzie M2, zmienna t odwołuje się już do innego obiektu tablicy. Linijka

t = new int[3];

powoduje zmianę wartości zmiennej tablicowe, a nie obiektu, a przy przesyłaniu przez wartość, co już wspominano wcześniej, zmiany wartości parametru formalnego nie są przenoszone na parametr aktualny.

W przypadku gdyby parametr był przesyłany przez referencję lub jako parametr wyjściowy, zmiana wartości zmienne, którą reprezentuje parametr formalny, pociąga za sobą zmianę w parametrze aktualnym.

Poniższy kod

static void M3(ref int [] t)
{
t = new int[3];
t[0] = 1;
}

...
int [] tab = {10,11,12};
M3(ref tab);
Console.Write(tab[0]);

spowoduje więc, że na ekranie pojawi się:

1

Przesyłanie dowolnej liczby argumentów

0x08 graphic

W języku C# istnieje mechanizm przesyłania dowolnej liczby argumentów do metody. Wykorzystywany jest choćby w metodzie Write, klasy Console.

Do oznaczenia, że metoda może przyjąć dowolną liczbę parametrów, używamy słowa kluczowego params w połączeniu z deklaracją argumentu typu jednowymiarowej tablicy np.:

static double Suma(params double [] skladniki)
{
double suma = 0;
foreach(double x in skladniki)
suma += x;
return suma;
}

Powyższą metodę możemy wywołać na dwa sposoby:

  1. Przesyłając jako argument tablicę

    double [] t = {1.3,2.4,3.1,4.3};
    double x = Suma(t);

  2. Przesyłając jako argument listę elementów. Lista może być również pusta. Jako element może występować dowolne wyrażenie, którego typ jest zgodny z typem podstawowym tablicy występującej po słowie params.

    double y = Suma(1.3,2.4,3.1,4.3);

    W przypadku powyższego wywołania, automatycznie tworzony jest obiekt tablicy.

W przypadku definiowania metody z dowolną liczbą parametrów należy pamiętać:

0x08 graphic
Przeciążenie nazwy metody

W poprzednim rozdziale wspominano, że wyjątkiem od reguły tworzenia unikalnych nazw, jest możliwość nadania takiej samej nazwy zmiennej współdzielonej i zmiennej lokalnej. Drugim wyjątkiem od reguły, że w jednym bloku kodu nie może występować dwóch takich samych identyfikatorów, jest mechanizm zwany przeciążeniem nazwy metody. Przeciążenie nazwy metody lub krócej przeciążenie metody, polega na nadaniu kilku metodom jednej klasy tej samej nazwy. Jest to możliwe, ponieważ w trakcie kompilacji nazwa metody jest rozszerzana o typ argumentów przekazywanych do metody. Metody należące do jednej klasy muszą różnić się sygnaturą. Na sygnaturę metody składają się:

Do sygnatury metody nie należą:

Dopuszczalna jest więc następująca definicja klasy (przykład przeciążenia nazwy metody):

class MetodyPrzeciazone
{
static void Nazwa(){...}
static void Nazwa(int i){...}
static void Nazwa(int i,int y){...}
static void Nazwa(ref int i){...}
static void Nazwa(double x){...}
static void Nazwa(double x,int i){...}
static void Nazwa(int i,double x){...}
}

Niedopuszczalne są następujące pary metod w jednej klasie:

Napotykając wywołanie metody, której nazwa jest przeciążona, kompilator wybiera odpowiednią metodę na podstawie typu argumentów aktualnych.

Nie można nadawać takich samych nazw metodzie i innym składnikom klasy: zmiennym współdzielonym, nazwom typów zdefiniowanych w klasie lub stałym nazwanym.

Stosowanie jednakowych nazw dla kilku metod tej samej klasy powinno być używane bardzo roztropnie, gdyż może powodować trudności z utrzymaniem kodu.

0x08 graphic
Argument metody Main

Uruchamiając program, można przekazać do niego pewną informację - argumenty w wierszu wywołania. W celu uruchomienia programu z argumentami w linii poleceń wydajemy następującą komendę.

NazwaProgramu arg1 arg2<ENTER>

W środowisku Visual Studio można również ustawić argumenty linii poleceń. Ustawia się je w oknie Właściwości Projektu (Menu Project/Nazwa Projektu Properties...) na zakładce Debug, w polu edycyjnym Command line arguments:.

Argumenty podane w wierszu wywołania programu, są przekazywane do programu za pomocą tablicy napisów (string), która jest parametrem metody Main.
Chcąc przetwarzać argumenty linii poleceń musimy jako punkt startowy naszego programu użyć metody Main z argumentem.

static int Main(string[] args)

lub

static void Main(string[] args)

Poniższy program wypisuje na ekranie wszystkie argumenty, które zostały podane w wierszu wywołania.

static int Main(string[] args)
{
foreach (string s in args)
Console.WriteLine(s);
Console.ReadKey();
return 0;
}

Przykład demonstrujący użycie argumentów linii wywołania można znaleźć w programie ArgumentyMain, który stanowi część rozwiązania Kurs\Demo\Modul9\Modul9.sln, gdzie Kurs jest katalogiem, gdzie skopiowano pliki kursu.

0x08 graphic
Pytania sprawdzające

  1. Wymień trzy sposoby przesyłania parametrów do metody.

    Odp.
    Argumenty do metody możemy przesyłać:

    1. Przez wartość.

    2. Przez referencję.

    3. Jako parametr wyjściowy

  2. Co należy do sygnatury metody?

    Odp.
    Do sygnatury metody należ: nazwa metody, typ parametrów, ilość parametrów, modyfikator typu parametru

  3. Zaznacz prawidłowe formy przeciążenia metody:
    static double Dodaj(int x, double y)

    1. static double Dodaj(int a, double b)

    2. static double Dodaj(double x, double y)

    3. static double Dodaj()

    4. static double Dodaj(ref int x,out double y)

    5. static int Dodaj(int x, double y)

Odp.
Prawidłowe odpowiedzi to: b, c, d.

  1. Co zostanie wypisane na ekranie?

    static void DodajJeden(double [] t){
    for(int i=0; i<t.Lenght;i++)
    t[i]++;
    }
    static void Main(){
    double [] tab = {1,2,3,4};
    DodajJeden(tab);
    foreach(double d in tab)
    Console.Write("{0}, ",d);
    }

    Odp.
    Na ekranie zostanie wypisane: 2, 3, 4, 5

  2. Jaki popełniono błąd w poniższym kodzie?

    static void Wypisz(out double d){
    Console.Write("d = {0}",d)
    }

    Odp.
    W powyższym kodzie pobierany wartość niezainicjalizowanej zmiennej. Argumenty przesyłane jako parametr wyjściowy są traktowane przez kompilator jako niezainicjalizowane.

0x08 graphic
Laboratorium

Ćwiczenie 1:
Napisz dwie metody obliczające wartość wielomianu metodą Hornera. Pierwsza metoda oblicza tylko wartość wielomianu dla wartości x podanej jako argument metody i zwraca ją do programu. Współczynniki wielomianu przesyłane są jako parametr z modyfikatorem params (dowolna ilość argumentów). Druga metoda dodatkowo oblicza stopień wielomianu - argument przesyłany jako parametr wyjściowy.

W metodzie Hornera stosuje się następujące przekształcenie :

a0xn + a1xn-1 + a2xn-2 +... +an-1x1 + an = (...((a0x + a1)*x + a2)*x+...+an-1)*x + an

W wyniku zastosowania powyższego przekształcenia zmniejszamy ilość wykonywanych działań i zwiększamy dokładność obliczonego wyniku.

  1. Uruchom Visual Studio
    Naciśnij przycisk Start systemu Windows, wybierz Wszystkie Programy następnie Microsoft Visual Studio 2005/ Microsoft Visual Studio 2005.

  2. Utwórz nowy projekt

    1. Z menu File wybierz New/Project...

    2. W oknie dialogowym New Project określ następujące właściwości:

      1. typu projektu: Visual C#/Windows

      2. szablon: Console Application

      3. lokalizacja: Moje Dokumenty\Visual Studio 2005\Projects\

      4. nazwa projektu: Wielomian.

      5. nazwa rozwiązania: Lab9

  3. Wewnątrz klasy Program utwórz metodę Wielomian, która zwraca wartość wielomianu dla wartości x podanej jako argument metody. Parametry wielomianu są przekazywane jako argument z modyfikatorem params.

    static double Wielomian(double x,params double[] a)
    {
    double suma = a[0];
    for (int i = 1; i < a.Length; i++)
    {
    suma = suma * x + a[i];
    }
    return suma;
    }

  4. Do klasy Program dodaj drugą metodę Wielomian, W odróżnieniu od metody zdefiniowanej w punkcie poprzednim, metoda ta posiada dodatkowy argument przesyłany jako parametr wyjściowy w którym zawarta jest informacja o stopniu wielomianu.

    static double Wielomian(double x,
    out double stopien, params double[] a)
    {
    stopien = a.Length - 1;
    for (int i = 0; i < a.Length - 1; i++)
    {
    if (a[i] != 0)
    break;
    stopien--;
    }
    return Wielomian(x, a);
    }

  5. Wewnątrz metody Main napisz następujący kod testujący metody zdefiniowane w poprzednich krokach:
    static void Main(string[] args)
    {
    double stopienWielomianu;
    double[] wspolczynnikiWielomianu={1, 1, 0, 1};

    Console.WriteLine("Wartość wielomianu obliczona
    ¬pierwszą metodą {0}",
    Wielomian(1,wspolczynnikiWielomianu));
    Console.WriteLine("Wartość wielomianu obliczona
    ¬drugą metodą {0}",
    Wielomian(1,out stopienWielomianu,
    wspolczynnikiWielomianu));
    Console.WriteLine("Stopień wielomianu: {0}",
    stopienWielomianu);

    Console.WriteLine("\nInny sposób przekazania
    ¬ wartości współczynników wielomianu
    ¬do metody");
    Console.WriteLine("Wartość wielomianu obliczona
    ¬pierwszą metodą {0}",
    Wielomian(1, 0,1,2));
    Console.WriteLine("Wartość wielomianu obliczona
    ¬drugą metodą {0}",
    Wielomian(1, out stopienWielomianu,
    0, 1, 2));
    Console.WriteLine("Stopień wielomianu: {0}",
    stopienWielomianu);
    Console.ReadKey();
    }

  6. Skompiluj i uruchom program.

Ćwiczenie 2:
Napisz dwie metody sortujące tablice. Pierwsza niech sortuje tablice liczb rzeczywistych. Druga metoda będzie sortowała tablice napisów. Do porównania dwóch napisów użyj metody String.Compare(string s1,string s2). Metoda ta zwraca wartość mniejszą od zera, gdy s1 jest "mniejsze" od s2, wartość zero gdy oba napisy są jednakowe oraz wartość większą od zera gdy s1 jest później w kolejności alfabetycznej niż s2. Więcej na temat metody Compare można znaleźć w MSDN Library.

Do sortowania użyj algorytmu sortowania przez kopcowanie (heap sort). Podstawą tej metody jest tworzenie tzw. kopca. Kopiec definiujemy jako ciąg elementów tablicy a[p], a[p+1], ..., a[q] spełniających następujące warunki:

dla wszystkich i = p, ..., (q-1)/2

Schemat blokowy metody sortowanie przez kopcowanie znajduje się w pliku Kurs\Lab\Modul9\Start\Przezkopcowanie.gif, a metody Przesiew, która jest wykorzystywana w metodzie sortującej, w pliku Kurs\Lab\Modul9\Start\Przesiew.gif, gdzie Kurs jest katalogiem gdzie skopiowano pliki kursu.

  1. Dodaj do bieżącego rozwiązania nowy projekt

  1. Z menu File wybierz Add/New Project...

  2. W oknie dialogowym Add New Project określ następujące właściwości:

      1. typu projektu: Visual C#/Windows

      2. szablon: Console Application

      3. nazwa projektu: SortowanieStogowe.

  1. Uczyń nowo utworzony projekt projektem startowym

  1. Zaznacz projekt SortowanieStogowe w okienku Solution Explorer i z menu kontekstowego wybierz Set as StartUp Project.

albo, gdy rozpoczynasz laboratorium od tego ćwiczenia

  1. Uruchom Visual Studio
    Naciśnij przycisk Start systemu Windows, wybierz Wszystkie Programy następnie Microsoft Visual Studio 2005/ Microsoft Visual Studio 2005.

  2. Utwórz nowy projekt

  1. Z menu File wybierz New/Project...

  2. W oknie dialogowym New Project określ następujące właściwości:

  1. typu projektu: Visual C#/Windows

  2. szablon: Console Application

  3. lokalizacja: Moje Dokumenty\Visual Studio 2005\Projects\

  4. nazwa projektu: SortowanieStogowe.

  5. nazwa rozwiązania: Lab9

  1. Do klasy Program dodaj metodę Przesiewaj, której działanie jest określone przez schemat blokowy w pliku Przesiew.gif. Typ double przyjmij jako typ podstawowy tablicy.

    static void Przesiewaj(double[] tab,uint l,uint p)
    {
    uint i = l,j = 2*i+1;
    double x = tab[i];
    while(j<=p)
    {
    if(j<p)
    if(tab[j]<tab[j+1])
    j++;
    if(tab[j]<x)
    break;
    tab[i] = tab[j];
    i=j;
    j=2*i+1;
    }
    if(i != l)
    tab[i] = x;
    }

  2. Do klasy Program dodaj metodę Przesiewaj, której działanie jest określone przez schemat blokowy w pliku Przesiew.gif. Typ string przyjmij jako typ podstawowy tablicy. Do porównania elementów tablicy, zmiast operatora mniejszości <, używaj metodę Comapre klasy string.

    static void Przesiewaj(string[] tab,uint l,uint p)
    {
    uint i = l, j = 2 * i + 1;
    string x = tab[i];
    while (j <= p)
    {
    if (j < p)
    if (string.Compare(tab[j],tab[j + 1])<0)
    j++;
    if (string.Compare(tab[j], x)<0)
    break;
    tab[i] = tab[j];
    i = j;
    j = 2 * i + 1;
    }
    if (i != l)
    tab[i] = x;
    }

  3. Do klasy Program dodaj metodę Sortuj, której działanie jest określone przez schemat blokowy w pliku Przezkopcowanie.gif. Typ double przyjmij jako typ podstawowy tablicy.

    static void Sortuj(double [] tab)
    {
    uint l = (uint)tab.Length/2,
    p=(uint)tab.Length-1;
    double x;
    while(l>0)
    {
    l--;
    Przesiewaj(tab,l,p);
    }
    while(p>0)
    {
    x=tab[0];
    tab[0] = tab[p];
    tab[p] = x;
    p--;
    Przesiewaj(tab,0,p);
    }
    }

  4. Do klasy Program dodaj metodę Sortuj, której działanie jest określone przez schemat blokowy w pliku Przezkopcowanie.gif. Typ string przyjmij jako typ podstawowy tablicy.

    static void Sortuj(string [] tab)
    {
    uint l = (uint)tab.Length / 2,
    p = (uint)tab.Length - 1;
    string x;
    while (l > 0)
    {
    l--;
    Przesiewaj(tab, l, p);
    }
    while (p > 0)
    {
    x = tab[0];
    tab[0] = tab[p];
    tab[p] = x;
    p--;
    Przesiewaj(tab, 0, p);
    }
    }

  5. Wewnątrz metody Main napisz kod testujący obie metody Sortuj.

    static void Main(string[] args)
    {
    double[] tab = { 2.3, 3, 45, 12.3, 4.3, 7.2 };
    Console.WriteLine("Tablica liczb rzeczywistych
    ¬przed sortowaniem");
    foreach (double d in tab)
    Console.Write("{0}; ", d);
    Sortuj(tab);
    Console.WriteLine("\nTablica liczb
    ¬rzeczywistych po sortowanu");
    foreach (double d in tab)
    Console.Write("{0}; ", d);
    Console.WriteLine("\n\n*****************\n");
    string[] napisy = { "szafa", "Szwecja",
    "szalik", "siano", "stóg",
    "szampan", "Słowacja" };
    Console.WriteLine("Tablica wyrazów przed
    ¬sortowaniem");
    foreach (string s in napisy)
    Console.Write("{0}; ", s);
    Sortuj(napisy);
    Console.WriteLine("\nTablica wyrazów po
    ¬sortowanu");
    foreach (string s in napisy)
    Console.Write("{0}; ", s);
    Console.ReadKey();
    }

  6. Skompiluj i uruchom program.0x01 graphic

L

L



Wyszukiwarka

Podobne podstrony:
Modul2, Courseware Development Tools
Modul1, Courseware Development Tools
Modul1, Courseware Development Tools
Modul3, Courseware Development Tools
Modul7, Courseware Development Tools
Modul8, Courseware Development Tools
Modul6, Courseware Development Tools
Modul12, Courseware Development Tools
4 ABAP Development Tools
GameBoy Development Tools
101 Learning and Development Tools Rok wydania 2011 oprawa miekka
Developing Usability Tools And Techniques For Designing And Testing Web Sites
A Grammar Development Course
A Grammar Development Course
Course hydro pl 1
4 Plant Structure, Growth and Development, before ppt
Marketing Management Course
Human Development Index

więcej podobnych podstron