Menerapkan metode dan parameter kelas

Selesai

Metode adalah blok kode yang berisi serangkaian pernyataan. Program menyebabkan pernyataan dijalankan dengan memanggil metode dan menentukan argumen metode yang diperlukan. Dalam C#, setiap instruksi yang dijalankan dilakukan dalam konteks metode.

Tanda tangan metode

Metode dideklarasikan dalam kelas, rekaman, atau struktur dengan menentukan:

  • Tingkat akses opsional, seperti public atau private. Defaultnya adalah private.
  • Pengubah opsional seperti abstract atau sealed.
  • Nilai yang dikembalikan, atau void jika metode tidak memilikinya.
  • Nama metode.
  • Parameter metode apa pun. Parameter metode diapit dalam tanda kurung dan dipisahkan oleh koma. Tanda kurung kosong menunjukkan bahwa metode tidak memerlukan parameter.

Bagian-bagian ini bekerja sama untuk membentuk tanda tangan metode.

Penting

Jenis pengembalian metode bukan bagian dari tanda tangan metode untuk tujuan kelebihan beban metode. Namun, ini adalah bagian dari tanda tangan metode saat menentukan kompatibilitas antara delegasi dan metode yang ditunjukkannya.

Contoh berikut mendefinisikan kelas bernama Motorcycle yang berisi lima metode:


namespace MotorCycleExample
{
    abstract class Motorcycle
    {
        // Anyone can call this.
        public void StartEngine() {/* Method statements here */ }

        // Only derived classes can call this.
        protected void AddGas(int gallons) { /* Method statements here */ }

        // Derived classes can override the base class implementation.
        public virtual int Drive(int miles, int speed) { /* Method statements here */ return 1; }

        // Derived classes can override the base class implementation.
        public virtual int Drive(TimeSpan time, int speed) { /* Method statements here */ return 0; }

        // Derived classes must implement this.
        public abstract double GetTopSpeed();
    }
}

Kelas Motorcycle mencakup metode yang kelebihan beban, Drive. Dua metode Drive memiliki nama yang sama, tetapi jenis parameter yang berbeda.

Pemanggilan metode

Metode dapat berupa instans atau statis. Anda harus membuat instans objek untuk memanggil metode instans pada instans tersebut; metode instans beroperasi pada instans tersebut dan datanya. Anda memanggil metode statis dengan merujuk nama jenis tempat metode berada; Metode statis tidak beroperasi pada data instans. Mencoba memanggil metode statis melalui instans objek menghasilkan kesalahan kompilator.

Memanggil metode seperti mengakses bidang. Setelah nama objek (jika Anda memanggil metode instans) atau nama jenis (jika Anda memanggil metode statis), tambahkan titik, nama metode, dan tanda kurung. Argumen tercantum dalam tanda kurung dan dipisahkan oleh koma.

Definisi metode menentukan nama dan jenis parameter apa pun yang diperlukan. Ketika penelepon memanggil metode , pemanggil menyediakan nilai konkret, yang disebut argumen, untuk setiap parameter. Argumen harus kompatibel dengan jenis parameter, tetapi nama argumen, jika argumen digunakan dalam kode panggilan, tidak harus sama dengan parameter bernama yang ditentukan dalam metode . Dalam contoh berikut, metode Square menyertakan satu parameter jenis int bernama i. Panggilan metode pertama melewati metode Square variabel jenis int bernama num; yang kedua, konstanta numerik; dan yang ketiga, ekspresi.


public static class SquareExample
{
    public static void Main()
    {
        // Call with an int variable.
        int num = 4;
        int productA = Square(num);

        // Call with an integer literal.
        int productB = Square(12);

        // Call with an expression that evaluates to int.
        int productC = Square(productA * 3);
    }

    static int Square(int i)
    {
        // Store input argument in a local variable.
        int input = i;
        return input * input;
    }
}

Parameter nilai dan referensi

Jenis dalam C# adalah jenis nilai atau jenis referensi. Secara default, jenis nilai dan jenis referensi diteruskan oleh nilai ke metode .

Parameter jenis nilai

Ketika jenis nilai diteruskan ke metode menurut nilai, salinan objek alih-alih objek itu sendiri diteruskan ke metode . Oleh karena itu, perubahan pada objek dalam metode yang disebut tidak berpengaruh pada objek asli saat kontrol kembali ke pemanggil.

Contoh berikut meneruskan jenis nilai ke metode menurut nilai, dan metode yang disebut mencoba mengubah nilai jenis nilai. Ini mendefinisikan variabel jenis int, yang merupakan jenis nilai, menginisialisasi nilainya menjadi 20, dan meneruskannya ke metode bernama ModifyValue yang mengubah nilai variabel menjadi 30. Namun, ketika metode mengembalikan, nilai variabel tetap tidak berubah.


public static class ByValueExample
{
    public static void Main()
    {
        var value = 20;
        Console.WriteLine("In Main, value = {0}", value);
        ModifyValue(value);
        Console.WriteLine("Back in Main, value = {0}", value);
    }

    static void ModifyValue(int i)
    {
        i = 30;
        Console.WriteLine("In ModifyValue, parameter value = {0}", i);
        return;
    }
}
// The example displays the following output:
//      In Main, value = 20
//      In ModifyValue, parameter value = 30
//      Back in Main, value = 20

Ketika objek dari jenis referensi diteruskan ke metode menurut nilai, referensi ke objek diteruskan oleh nilai. Artinya, metode ini tidak menerima objek itu sendiri, tetapi argumen yang menunjukkan lokasi objek. Jika Anda mengubah anggota objek dengan menggunakan referensi ini, perubahan tercermin dalam objek saat kontrol kembali ke metode panggilan. Namun, mengganti objek yang diteruskan ke metode tidak berpengaruh pada objek asli saat kontrol kembali ke pemanggil.

Contoh berikut mendefinisikan kelas (yang merupakan jenis referensi) bernama SampleRefType. Ini membuat instans objek SampleRefType, menetapkan 44 ke bidang value, dan meneruskan objek ke metode ModifyObject. Contoh ini pada dasarnya melakukan hal yang sama dengan contoh sebelumnya (meneruskan argumen berdasarkan nilai ke metode). Namun, hasilnya berbeda karena jenis referensi digunakan daripada jenis nilai. Modifikasi yang dibuat dalam ModifyObject ke bidang obj.value juga mengubah bidang value argumen, rt. Ketika metode Main menampilkan nilai rt kita melihat bahwa metode tersebut telah diperbarui ke 33, seperti yang ditunjukkan oleh output dari contoh.


public class SampleRefType
{
    public int value;
}

public static class ByRefTypeExample
{
    public static void Main()
    {
        var rt = new SampleRefType { value = 44 };
        Console.WriteLine("In Main, rt.value = {0}", rt.value);
        ModifyObject(rt);
        Console.WriteLine("Back in Main, rt.value = {0}", rt.value);
    }

    static void ModifyObject(SampleRefType obj)
    {
        obj.value = 33;
        Console.WriteLine("In ModifyObject, obj.value = {0}", obj.value);
    }
}
// The example displays the following output:
//      In Main, rt.value = 44
//      In ModifyObject, obj.value = 33
//      Back in Main, rt.value = 33

Parameter jenis referensi

Anda meneruskan parameter menurut referensi saat Anda ingin mengubah nilai argumen dalam metode dan ingin mencerminkan perubahan tersebut saat kontrol kembali ke metode panggilan. Untuk meneruskan parameter menurut referensi, Anda menggunakan kata kunci ref atau out. Anda juga dapat meneruskan nilai berdasarkan referensi untuk menghindari penyalinan tetapi masih mencegah modifikasi menggunakan kata kunci in.

Contoh berikut identik dengan yang sebelumnya kecuali nilai diteruskan dengan referensi ke metode ModifyValue. Ketika nilai parameter dimodifikasi dalam metode ModifyValue, perubahan nilai tercermin saat kontrol kembali ke pemanggil.


public static class ByRefExample
{
    public static void Main()
    {
        var value = 20;
        Console.WriteLine("In Main, value = {0}", value);
        ModifyValue(ref value);
        Console.WriteLine("Back in Main, value = {0}", value);
    }

    private static void ModifyValue(ref int i)
    {
        i = 30;
        Console.WriteLine("In ModifyValue, parameter value = {0}", i);
        return;
    }
}
// The example displays the following output:
//      In Main, value = 20
//      In ModifyValue, parameter value = 30
//      Back in Main, value = 30

Pola umum yang digunakan oleh parameter ref melibatkan penukaran nilai variabel. Anda meneruskan dua variabel ke metode berdasarkan referensi, dan metode menukar kontennya. Contoh berikut menukar nilai bilangan bulat.


public static class RefSwapExample
{
    static void Main()
    {
        int i = 2, j = 3;
        Console.WriteLine("i = {0}  j = {1}", i, j);

        Swap(ref i, ref j);

        Console.WriteLine("i = {0}  j = {1}", i, j);
    }

    static void Swap(ref int x, ref int y) =>
        (y, x) = (x, y);
}
// The example displays the following output:
//      i = 2  j = 3
//      i = 3  j = 2

Meneruskan parameter jenis referensi memungkinkan Anda mengubah nilai referensi itu sendiri, bukan nilai elemen atau bidang individualnya.

Koleksi parameter

Terkadang, persyaratan yang Anda tentukan jumlah argumen yang tepat untuk metode Anda bersifat ketat. Dengan menggunakan kata kunci params untuk menunjukkan bahwa parameter adalah koleksi parameter, Anda memungkinkan metode Anda dipanggil dengan jumlah variabel argumen. Parameter yang ditandai dengan kata kunci params harus merupakan jenis koleksi, dan harus menjadi parameter terakhir dalam daftar parameter metode.

Pemanggil kemudian dapat memanggil metode dengan salah satu dari empat cara untuk parameter param:

  • Dengan meneruskan koleksi jenis yang sesuai yang berisi jumlah elemen yang diinginkan. Contoh menggunakan ekspresi koleksi sehingga pengkompilasi membuat jenis koleksi yang sesuai.
  • Dengan meneruskan daftar argumen individual yang dipisahkan koma dari jenis yang sesuai ke metode . Pengkompilasi membuat jenis koleksi yang sesuai.
  • Dengan melewati null.
  • Dengan tidak memberikan argumen ke koleksi parameter.

Contoh berikut mendefinisikan metode bernama GetVowels yang mengembalikan semua vokal dari koleksi parameter. Metode Main mengilustrasikan keempat cara memanggil metode . Penelepon tidak diperlukan untuk menyediakan argumen apa pun untuk parameter yang menyertakan pengubah params. Dalam hal ini, parameter adalah koleksi kosong.


static class ParamsExample
{
    static void Main()
    {
        string fromArray = GetVowels(["apple", "banana", "pear"]);
        Console.WriteLine($"Vowels from collection expression: '{fromArray}'");

        string fromMultipleArguments = GetVowels("apple", "banana", "pear");
        Console.WriteLine($"Vowels from multiple arguments: '{fromMultipleArguments}'");

        string fromNull = GetVowels(null);
        Console.WriteLine($"Vowels from null: '{fromNull}'");

        string fromNoValue = GetVowels();
        Console.WriteLine($"Vowels from no value: '{fromNoValue}'");
    }

    static string GetVowels(params IEnumerable<string>? input)
    {
        if (input == null || !input.Any())
        {
            return string.Empty;
        }

        char[] vowels = ['A', 'E', 'I', 'O', 'U'];
        return string.Concat(
            input.SelectMany(
                word => word.Where(letter => vowels.Contains(char.ToUpper(letter)))));
    }
}

// The example displays the following output:
//     Vowels from array: 'aeaaaea'
//     Vowels from multiple arguments: 'aeaaaea'
//     Vowels from null: ''
//     Vowels from no value: ''

Nota

Sebelum C# 13, pengubah params hanya dapat digunakan dengan array dimensi tunggal.

Mengembalikan nilai metode

Metode dapat mengembalikan nilai ke pemanggil. Jika jenis pengembalian (jenis yang tercantum sebelum nama metode) tidak void, metode dapat mengembalikan nilai dengan menggunakan kata kunci return. Pernyataan dengan kata kunci return diikuti dengan variabel, konstanta, atau ekspresi yang cocok dengan jenis pengembalian mengembalikan nilai tersebut ke pemanggil metode. Metode dengan jenis pengembalian nonvoid diperlukan untuk menggunakan kata kunci return untuk mengembalikan nilai. Kata kunci return juga menghentikan eksekusi metode.

Jika jenis pengembalian void, pernyataan pengembalian tanpa nilai masih berguna untuk menghentikan eksekusi metode. Tanpa kata kunci return, metode berhenti dijalankan ketika mencapai akhir blok kode.

Misalnya, kedua metode ini menggunakan kata kunci return untuk mengembalikan bilangan bulat:


class SimpleMath
{
    public int AddTwoNumbers(int number1, int number2) =>
        number1 + number2;

    public int SquareANumber(int number) =>
        number * number;
}

Contoh ini menggunakan anggota bertubuh ekspresi untuk menetapkan nilai pengembalian metode. Sintaks ini adalah singkatan untuk metode yang menggunakan pernyataan tunggal (ekspresi) untuk menghitung nilai yang dikembalikan.

Anda juga dapat memilih untuk menentukan metode Anda dengan isi pernyataan dan pernyataan return:


class SimpleMathExtnsion
{
    public int DivideTwoNumbers(int number1, int number2)
    {
        return number1 / number2;
    }
}

Untuk menggunakan nilai yang dikembalikan dari metode , metode panggilan dapat menggunakan metode memanggil dirinya sendiri di mana saja nilai dengan jenis yang sama akan cukup. Anda juga dapat menetapkan nilai pengembalian ke variabel. Misalnya, tiga contoh kode berikut mencapai tujuan yang sama:


int result = obj.AddTwoNumbers(1, 2);
result = obj.SquareANumber(result);
// The result is 9.
Console.WriteLine(result);


result = obj.SquareANumber(obj.AddTwoNumbers(1, 2));
// The result is 9.
Console.WriteLine(result);


result = obj2.DivideTwoNumbers(6,2);
// The result is 3.
Console.WriteLine(result);

Terkadang, Anda ingin metode Anda mengembalikan lebih dari satu nilai. Anda menggunakan tipe tuple dan tuple literal untuk mengembalikan beberapa nilai. Jenis tuple mendefinisikan jenis data elemen tuple. Literal tuple memberikan nilai aktual dari tuple yang dikembalikan. Dalam contoh berikut, (string, string, string, int) menentukan jenis tuple yang dikembalikan oleh metode GetPersonalInfo. Ekspresi (per.FirstName, per.MiddleName, per.LastName, per.Age) adalah tuple harfiah; metode mengembalikan nama pertama, tengah, dan keluarga, bersama dengan usia, dari objek PersonInfo.


public (string, string, string, int) GetPersonalInfo(string id)
{
    PersonInfo per = PersonInfo.RetrieveInfoById(id);
    return (per.FirstName, per.MiddleName, per.LastName, per.Age);
}

Pemanggil kemudian dapat menggunakan tuple yang dikembalikan menggunakan kode berikut:


var person = GetPersonalInfo("111111111");
Console.WriteLine($"{person.Item1} {person.Item3}: age = {person.Item4}");

Nama juga dapat ditetapkan ke elemen tuple dalam definisi jenis tuple. Contoh berikut menunjukkan versi alternatif metode GetPersonalInfo yang menggunakan elemen bernama:


public (string FName, string MName, string LName, int Age) GetPersonalInfo(string id)
{
    PersonInfo per = PersonInfo.RetrieveInfoById(id);
    return (per.FirstName, per.MiddleName, per.LastName, per.Age);
}

Panggilan sebelumnya ke metode GetPersonalInfo kemudian dapat dimodifikasi sebagai berikut:


var person = GetPersonalInfo("111111111");
Console.WriteLine($"{person.FName} {person.LName}: age = {person.Age}");

Jika metode mengambil array sebagai parameter dan memodifikasi nilai elemen individual, metode tidak diperlukan untuk mengembalikan array. C# meneruskan semua jenis referensi menurut nilai, dan nilai referensi array adalah penunjuk ke array.

Anggota bertubuh ekspresi

Adalah umum untuk memiliki definisi metode yang segera kembali dengan hasil ekspresi, atau yang memiliki satu pernyataan sebagai isi metode. Ada pintasan sintaksis untuk menentukan metode tersebut menggunakan =>:


public Point Move(int dx, int dy) => new Point(x + dx, y + dy);
public void Print() => Console.WriteLine(First + " " + Last);
// Works with operators, properties, and indexers too.
public static Complex operator +(Complex a, Complex b) => a.Add(b);
public string Name => First + " " + Last;
public Customer this[long id] => store.LookupCustomer(id);

Jika metode mengembalikan void atau merupakan metode asinkron, isi metode harus berupa ekspresi pernyataan (sama seperti lambda). Untuk properti dan pengindeks, properti harus bersifat baca-saja, dan Anda tidak menggunakan kata kunci aksesor get.