Bagikan melalui


Metode dalam C#

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

Catatan

Topik ini membahas metode bernama. Untuk informasi tentang fungsi anonim, lihat Ekspresi Lambda .

Tanda tangan metode

Metode dideklarasikan dalam class, record, atau struct dengan menetapkan:

  • Tingkat akses opsional, seperti public atau private. Default 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 dengan koma. Tanda kurung kosong menunjukkan bahwa metode tidak memerlukan parameter.

Bagian-bagian ini bersama-sama membentuk tanda tangan metode.

Penting

Jenis pengembalian metode bukan bagian dari tanda tangan metode untuk tujuan metode kelebihan beban. 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 menyertakan metode overload, Drive. Dua metode memiliki nama yang sama, tetapi dibingkai oleh jenis parameternya.

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 statik dengan merujuk nama jenis tempat metode berada; metode statik tidak beroperasi pada data instans. Mencoba memanggil metode statis melalui instans objek menghasilkan kesalahan pengompilasi.

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

Definisi metode menentukan nama dan jenis parameter apa pun yang diperlukan. Ketika memanggil metode, pemanggil menyediakan nilai konkret, yang disebut argumen, untuk setiap parameter. Argumen harus kompatibel dengan jenis parameter, tetapi nama argumen, jika salah satu 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 meneruskan metode variabel Square berjenis 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;
    }
}

Bentuk pemanggilan metode yang paling umum digunakan argumen posisi; ini memasok argumen dalam urutan yang sama dengan parameter metode. Oleh karena itu, metode kelas Motorcycle dapat dipanggil seperti dalam contoh berikut. Panggilan ke metode Drive, misalnya, menyertakan dua argumen yang sesuai dengan dua parameter dalam sintaks metode. Yang pertama menjadi nilai miles parameter. Yang kedua menjadi nilai speed parameter.

class TestMotorcycle : Motorcycle
{
    public override double GetTopSpeed() => 108.4;

    static void Main()
    {
        var moto = new TestMotorcycle();

        moto.StartEngine();
        moto.AddGas(15);
        _ = moto.Drive(5, 20);
        double speed = moto.GetTopSpeed();
        Console.WriteLine("My top speed is {0}", speed);
    }
}

Anda juga dapat menggunakan argumen bernama , bukan argumen posisi saat menjalankan metode. Saat menggunakan argumen bernama, Anda menentukan nama parameter diikuti dengan titik dua (":") dan argumen. Argumen ke metode dapat muncul dalam urutan apa pun, selama semua argumen yang diperlukan ada. Contoh berikut menggunakan argumen bernama untuk memanggil metode TestMotorcycle.Drive. Dalam contoh ini, argumen bernama dilewatkan dalam urutan yang berlawanan dari daftar parameter metode.

namespace NamedMotorCycle;

class TestMotorcycle : Motorcycle
{
    public override int Drive(int miles, int speed) =>
        (int)Math.Round((double)miles / speed, 0);

    public override double GetTopSpeed() => 108.4;

    static void Main()
    {
        var moto = new TestMotorcycle();
        moto.StartEngine();
        moto.AddGas(15);
        int travelTime = moto.Drive(miles: 170, speed: 60);
        Console.WriteLine("Travel time: approx. {0} hours", travelTime);
    }
}
// The example displays the following output:
//      Travel time: approx. 3 hours

Anda dapat memanggil metode menggunakan argumen posisi dan argumen bernama. Namun, argumen posisi hanya dapat mengikuti argumen bernama ketika argumen bernama berada di posisi yang benar. Contoh berikut memanggil metode TestMotorcycle.Drive dari contoh sebelumnya menggunakan satu argumen posisi dan satu argumen bernama.

int travelTime = moto.Drive(170, speed: 55);

Metode yang diwariskan dan diganti

Selain anggota yang secara eksplisit didefinisikan dalam jenis, jenis mewarisi anggota yang ditentukan dalam kelas dasarnya. Karena semua jenis dalam sistem jenis terkelola mewarisi secara langsung atau tidak langsung dari kelas Object, semua jenis mewarisi anggotanya, seperti Equals(Object), GetType(), dan ToString(). Contoh berikut mendefinisikan kelas Person, membuat instans dua objek Person, dan memanggil metode Person.Equals untuk menentukan apakah kedua objek tersebut sama. Namun, metode Equals tidak didefinisikan di kelas Person; metode ini diwarisi dari Object.

public class Person
{
    public string FirstName = default!;
}

public static class ClassTypeExample
{
    public static void Main()
    {
        Person p1 = new() { FirstName = "John" };
        Person p2 = new() { FirstName = "John" };
        Console.WriteLine("p1 = p2: {0}", p1.Equals(p2));
    }
}
// The example displays the following output:
//      p1 = p2: False

Jenis dapat mengganti anggota yang diwariskan dengan menggunakan kata kunci override dan menyediakan implementasi untuk metode yang diganti. Tanda tangan metode harus sama dengan metode yang ditimpa. Contoh berikut ini sama seperti contoh sebelumnya, kecuali menimpa metode Equals(Object). (Ini juga menggantikan metode GetHashCode(), karena kedua metode tersebut dimaksudkan untuk memberikan hasil yang konsisten.)

namespace methods;

public class Person
{
    public string FirstName = default!;

    public override bool Equals(object? obj) =>
        obj is Person p2 &&
        FirstName.Equals(p2.FirstName);

    public override int GetHashCode() => FirstName.GetHashCode();
}

public static class Example
{
    public static void Main()
    {
        Person p1 = new() { FirstName = "John" };
        Person p2 = new() { FirstName = "John" };
        Console.WriteLine("p1 = p2: {0}", p1.Equals(p2));
    }
}
// The example displays the following output:
//      p1 = p2: True

Parameter Passing

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

Meneruskan parameter menurut nilai

Ketika jenis nilai diteruskan ke metode berdasarkan nilai, salinan objek, bukan objek itu sendiri diteruskan ke metode. Oleh karena itu, perubahan pada objek dalam metode yang dipanggil tidak berpengaruh pada objek asli saat kontrol kembali ke pemanggil.

Contoh berikut meneruskan jenis nilai ke metode berdasarkan nilai, dan metode yang dipanggil 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 kembali, 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 berdasarkan 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-nya, dan meneruskan objek ke metode ModifyObject. Contoh ini pada dasarnya melakukan hal yang sama seperti contoh sebelumnya—contoh ini meneruskan argumen berdasarkan nilai ke suatu metode. Tetapi karena jenis referensi yang digunakan, hasilnya berbeda. Modifikasi yang dilakukan di ModifyObject ke bidang obj.value juga mengubah bidang argumen value, rt, dalam metode Main menjadi 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 };
        ModifyObject(rt);
        Console.WriteLine(rt.value);
    }

    static void ModifyObject(SampleRefType obj) => obj.value = 33;
}

Meneruskan parameter berdasarkan referensi

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

Contoh berikut identik dengan yang sebelumnya kecuali nilai diteruskan oleh referensi ke ModifyValue metode . Saat nilai parameter diubah dalam metode ModifyValue, perubahan nilai dicerminkan 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 pertukaran nilai variabel. Anda meneruskan dua variabel ke metode dengan referensi, dan metode menukar isinya. Contoh berikut mengganti 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 individunya.

Koleksi parameter

Terkadang, persyaratan bahwa Anda menentukan jumlah argumen yang tepat untuk metode Anda bersifat membatasi. Dengan menggunakan params kata kunci untuk menunjukkan bahwa parameter adalah koleksi parameter, Anda memungkinkan metode Anda dipanggil dengan jumlah variabel argumen. Parameter yang ditandai dengan params kata kunci 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 params parameter:

  • 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 individu yang dipisahkan koma dari jenis yang sesuai ke metode. Pengkompilasi membuat jenis koleksi yang sesuai.
  • Dengan meneruskan 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. Pemanggil tidak diharuskan memberikan 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: ''

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

Parameter dan argumen opsional

Definisi metode dapat menentukan bahwa parameternya diperlukan atau opsional. Secara default, parameter diperlukan. Parameter opsional ditentukan dengan menyertakan nilai default parameter dalam definisi metode. Saat metode dipanggil, jika tidak ada argumen yang diberikan untuk parameter opsional, nilai default digunakan sebagai gantinya.

Anda menetapkan nilai default parameter dengan salah satu jenis ekspresi berikut:

  • Konstanta, seperti string atau angka harfiah.

  • Ekspresi formulir default(SomeType), di mana SomeType dapat berupa jenis nilai atau jenis referensi. Jika jenis referensi, ekspresi secara efektif sama dengan menetapkan null. Anda dapat menggunakan default literal, karena pengkompilasi dapat menyimpulkan jenis dari deklarasi parameter.

  • Ekspresi formulir new ValType(), di mana ValType adalah jenis nilai. Ekspresi ini memanggil konstruktor tanpa parameter implisit jenis nilai, yang bukan anggota jenis aktual.

    Catatan

    Dalam C# 10 dan yang lebih baru, ketika ekspresi formulir new ValType() memanggil konstruktor tanpa parameter yang ditentukan secara eksplisit dari jenis nilai, pengompilasi menghasilkan kesalahan karena nilai parameter default harus berupa konstanta waktu kompilasi. Gunakan ekspresi default(ValType) atau harfiah default untuk memberikan nilai parameter default. Untuk informasi lebih lanjut tentang konstruktor tanpa parameter, lihat bagian Inisialisasi struktur dan nilai default di artikel Jenis struktur.

Jika suatu metode menyertakan parameter wajib dan opsional, parameter opsional ditentukan di akhir daftar parameter, setelah semua parameter wajib.

Contoh berikut mendefinisikan metode, ExampleMethod, yang memiliki satu parameter wajib dan dua parameter opsional.

public class Options
{
    public void ExampleMethod(int required, int optionalInt = default,
                              string? description = default)
    {
        var msg = $"{description ?? "N/A"}: {required} + {optionalInt} = {required + optionalInt}";
        Console.WriteLine(msg);
    }
}

Pemanggil harus menyediakan argumen untuk semua parameter opsional hingga parameter opsional terakhir yang argumennya disediakan. Dalam metode , ExampleMethod misalnya, jika pemanggil menyediakan argumen untuk description parameter , pemanggil juga harus menyediakannya untuk optionalInt parameter . opt.ExampleMethod(2, 2, "Addition of 2 and 2"); adalah panggilan metode yang valid; opt.ExampleMethod(2, , "Addition of 2 and 0"); menghasilkan kesalahan kompilator "Argumen hilang".

Jika metode dipanggil menggunakan argumen bernama atau kombinasi argumen posisi dan bernama, pemanggil dapat menghilangkan argumen apa pun yang mengikuti argumen posisi terakhir dalam panggilan metode.

Contoh berikut memanggil metode ExampleMethod tiga kali. Dua panggilan metode pertama menggunakan argumen posisi. Yang pertama menghilangkan kedua argumen opsional, sedangkan yang kedua menghilangkan argumen terakhir. Panggilan metode ketiga memasok argumen posisi untuk parameter yang diperlukan tetapi menggunakan argumen bernama untuk menyediakan nilai ke parameter description sambil menghilangkan argumen optionalInt.

public static class OptionsExample
{
    public static void Main()
    {
        var opt = new Options();
        opt.ExampleMethod(10);
        opt.ExampleMethod(10, 2);
        opt.ExampleMethod(12, description: "Addition with zero:");
    }
}
// The example displays the following output:
//      N/A: 10 + 0 = 10
//      N/A: 10 + 2 = 12
//      Addition with zero:: 12 + 0 = 12

Penggunaan parameter opsional memengaruhi resolusi kelebihan beban, atau cara pengkompilasi C# menentukan kelebihan beban mana yang akan dipanggil untuk panggilan metode, sebagai berikut:

  • Metode, pengindeks, atau konstruktor adalah kandidat untuk eksekusi jika setiap parameternya sesuai dengan nama atau berdasarkan posisi ke satu argumen, dan argumen tersebut dapat dikonversi ke jenis parameter.
  • Jika lebih dari satu kandidat ditemukan, aturan resolusi yang berlebihan untuk konversi pilihan akan diterapkan ke argumen yang ditentukan secara eksplisit. Argumen yang dihilangkan untuk parameter opsional diabaikan.
  • Jika dua kandidat dinilai sama baiknya, preferensi masuk ke kandidat yang tidak memiliki parameter opsional yang argumennya dihilangkan dalam panggilan.

Mengembalikan nilai

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

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

Misalnya, dua 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 di atas adalah anggota bertubuh ekspresi. Anggota bertubuh ekspresi mengembalikan nilai yang dikembalikan oleh ekspresi.

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

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 yang dikembalikan 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 jenis tuple dan literal tuple untuk mengembalikan beberapa nilai. Jenis tuple mendefinisikan jenis data dari elemen tuple. Harfiah tuple memberikan nilai sebenarnya dari tuple yang dikembalikan. Dalam contoh berikut, (string, string, string, int) menentukan jenis tuple yang dikembalikan oleh GetPersonalInfo metode . Ekspresinya (per.FirstName, per.MiddleName, per.LastName, per.Age) adalah tuple literal; metode mengembalikan nama pertama, tengah, dan keluarga, bersama dengan usia, 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 diberikan ke elemen tuple dalam definisi jenis tuple. Contoh berikut menunjukkan versi alternatif dari 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. Dalam contoh berikut, perubahan pada konten array values yang dibuat dalam metode DoubleValues dapat diamati oleh kode apa pun yang memiliki referensi ke array.


public static class ArrayValueExample
{
    static void Main()
    {
        int[] values = [2, 4, 6, 8];
        DoubleValues(values);
        foreach (var value in values)
        {
            Console.Write("{0}  ", value);
        }
    }

    public static void DoubleValues(int[] arr)
    {
        for (var ctr = 0; ctr <= arr.GetUpperBound(0); ctr++)
        {
            arr[ctr] *= 2;
        }
    }
}
// The example displays the following output:
//       4  8  12  16

Metode ekstensi

Biasanya, ada dua cara untuk menambahkan metode ke jenis yang sudah ada:

  • Ubah kode sumber untuk jenis tersebut. Memodifikasi sumber membuat perubahan yang melanggar jika Anda juga menambahkan bidang data privat untuk mendukung metode .
  • Mendefinisikan metode baru di kelas turunan. Metode tidak dapat ditambahkan dengan cara ini menggunakan warisan untuk jenis lain, seperti struktur dan enumerasi. Juga tidak dapat digunakan untuk "menambahkan" metode ke kelas yang disegel.

Metode ekstensi memungkinkan Anda "menambahkan" metode ke jenis yang ada tanpa mengubah jenis itu sendiri atau menerapkan metode baru dalam jenis yang diwariskan. Metode ekstensi juga tidak harus berada di rakitan yang sama dengan jenis yang diperluas. Anda memanggil metode ekstensi seolah-olah itu adalah anggota jenis yang ditentukan.

Untuk informasi selengkapnya, lihat Metode Ekstensi.

Metode Asinkron

Dengan menggunakan fitur asinkron, Anda dapat memanggil metode asinkron tanpa menggunakan panggilan balik eksplisit atau secara manual memisahkan kode Anda di beberapa metode atau ekspresi lambda.

Jika Anda menandai metode dengan pengubah asinkron, Anda dapat menggunakan operator menunggu dalam metode tersebut. Saat kontrol mencapai ekspresi await dalam metode asinkron, kontrol kembali ke pemanggil jika tugas yang ditunggu tidak selesai, dan progres dalam metode dengan kata kunci await ditangguhkan hingga tugas yang ditunggu selesai. Ketika tugas selesai, eksekusi dapat dilanjutkan dalam metode.

Catatan

Metode asinkron kembali ke pemanggil ketika menemukan objek pertama yang ditunggu yang belum selesai atau sampai ke akhir metode asinkron, mana yang terjadi terlebih dahulu.

Metode asinkron biasanya memiliki jenis pengembalian , Task<TResult>, Task, IAsyncEnumerable<T>atau void. Jenis pengembalian void digunakan terutama untuk menentukan penanganan aktivitas, di mana jenis pengembalian void diperlukan. Metode asinkron yang memiliki jenis pengembalian void tidak dapat ditunggu, dan pemanggil metode pengembalian void tidak dapat menangkap pengecualian apa pun yang ditampilkan metode tersebut. Metode asinkron dapat memiliki jenis pengembalian seperti tugas.

Dalam contoh berikut, DelayAsync adalah metode asinkron yang memiliki pernyataan pengembalian yang mengembalikan bilangan bulat. Karena ini adalah metode asinkron, deklarasi metodenya harus memiliki jenis pengembalian Task<int>. Karena jenis yang dikembalikan adalah Task<int>, evaluasi ekspresi await dalam DoSomethingAsync menghasilkan bilangan bulat, seperti yang ditunjukkan oleh pernyataan int result = await delayTask berikut.

class Program
{
    static Task Main() => DoSomethingAsync();

    static async Task DoSomethingAsync()
    {
        Task<int> delayTask = DelayAsync();
        int result = await delayTask;

        // The previous two statements may be combined into
        // the following statement.
        //int result = await DelayAsync();

        Console.WriteLine($"Result: {result}");
    }

    static async Task<int> DelayAsync()
    {
        await Task.Delay(100);
        return 5;
    }
}
// Example output:
//   Result: 5

Metode asinkron tidak dapat mendeklarasikan apa pun dalam parameter , ref, atau out, tetapi dapat memanggil metode yang memiliki parameter tersebut.

Untuk informasi selengkapnya tentang metode asinkron, lihat Pemrograman asinkron dengan asinkron dan menunggu dan Jenis pengembalian asinkron.

Anggota-yang mengisi ekspresi

Adalah umum untuk memiliki definisi metode yang segera kembali dengan hasil ekspresi, atau yang memiliki satu pernyataan sebagai isi metode. Ada pintasan sintaks untuk mendefinisikan 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, mereka harus baca-saja, dan Anda tidak menggunakan kata kunci pengakses get.

Iterator

Iterator melakukan perulangan kustom pada koleksi, seperti daftar atau array. Iterator menggunakan pernyataan yield return untuk mengembalikan setiap elemen satu per satu. Ketika pernyataan yield return tercapai, lokasi saat ini diingat sehingga pemanggil dapat meminta elemen berikutnya secara berurutan.

Jenis pengembalian iterator dapat berupa IEnumerable, , IEnumerable<T>, IAsyncEnumerable<T>IEnumerator, atau IEnumerator<T>.

Untuk informasi selengkapnya, lihat Iterator.

Lihat juga