Bagikan melalui


Cara melakukan konversi eksplisit dengan aman menggunakan pencocokan pola dan operator is dan as

Karena objek bersifat polimorfik, dimungkinkan bagi variabel jenis kelas dasar untuk menyimpan jenis turunan. Untuk mengakses anggota instans jenis turunan, Anda perlu mentransmisikan nilai kembali ke jenis turunan. Namun, transmisi menciptakan risiko melempar InvalidCastException. C# memberikan pernyataan pencocokan pola yang melakukan transmisi secara kondisional hanya jika itu akan berhasil. C# juga menyediakan operator is dan as untuk menguji apakah suatu nilai adalah jenis tertentu.

Contoh berikut menunjukkan cara menggunakan pernyataan is pencocokan pola:

var g = new Giraffe();
var a = new Animal();
FeedMammals(g);
FeedMammals(a);
// Output:
// Eating.
// Animal is not a Mammal

SuperNova sn = new SuperNova();
TestForMammals(g);
TestForMammals(sn);

static void FeedMammals(Animal a)
{
    if (a is Mammal m)
    {
        m.Eat();
    }
    else
    {
        // variable 'm' is not in scope here, and can't be used.
        Console.WriteLine($"{a.GetType().Name} is not a Mammal");
    }
}

static void TestForMammals(object o)
{
    // You also can use the as operator and test for null
    // before referencing the variable.
    var m = o as Mammal;
    if (m != null)
    {
        Console.WriteLine(m.ToString());
    }
    else
    {
        Console.WriteLine($"{o.GetType().Name} is not a Mammal");
    }
}
// Output:
// I am an animal.
// SuperNova is not a Mammal

class Animal
{
    public void Eat() { Console.WriteLine("Eating."); }
    public override string ToString()
    {
        return "I am an animal.";
    }
}
class Mammal : Animal { }
class Giraffe : Mammal { }

class SuperNova { }

Sampel sebelumnya menunjukkan beberapa fitur sintaks pencocokan pola. Pernyataan if (a is Mammal m) menggabungkan pengujian dengan penugasan inisialisasi. Penugasan hanya terjadi ketika pengujian berhasil. Variabel m hanya dalam cakupan di pernyataan if yang disematkan di mana variabel tersebut telah ditetapkan. Anda tidak dapat mengakses m nanti dengan metode yang sama. Contoh sebelumnya juga menunjukkan cara menggunakan operator as untuk mengonversi objek ke jenis yang ditentukan.

Anda juga dapat menggunakan sintaks yang sama untuk pengujian jika jenis nilai yang dapat diubah ke null memiliki nilai, seperti yang ditunjukkan pada contoh berikut:

int i = 5;
PatternMatchingNullable(i);

int? j = null;
PatternMatchingNullable(j);

double d = 9.78654;
PatternMatchingNullable(d);

PatternMatchingSwitch(i);
PatternMatchingSwitch(j);
PatternMatchingSwitch(d);

static void PatternMatchingNullable(ValueType? val)
{
    if (val is int j) // Nullable types are not allowed in patterns
    {
        Console.WriteLine(j);
    }
    else if (val is null) // If val is a nullable type with no value, this expression is true
    {
        Console.WriteLine("val is a nullable type with the null value");
    }
    else
    {
        Console.WriteLine("Could not convert " + val.ToString());
    }
}

static void PatternMatchingSwitch(ValueType? val)
{
    switch (val)
    {
        case int number:
            Console.WriteLine(number);
            break;
        case long number:
            Console.WriteLine(number);
            break;
        case decimal number:
            Console.WriteLine(number);
            break;
        case float number:
            Console.WriteLine(number);
            break;
        case double number:
            Console.WriteLine(number);
            break;
        case null:
            Console.WriteLine("val is a nullable type with the null value");
            break;
        default:
            Console.WriteLine("Could not convert " + val.ToString());
            break;
    }
}

Contoh sebelumnya menunjukkan fitur lain dari pencocokan pola untuk digunakan dengan konversi. Anda dapat menguji variabel untuk pola null dengan memeriksa secara khusus nilai null. Jika nilai runtime bahasa umum variabel adalah null, pernyataan is yang memeriksa jenis selalu mengembalikan false. Pernyataan pencocokan pola is tidak mengizinkan jenis nilai yang dapat diubah ke null, seperti int? atau Nullable<int>, tetapi Anda dapat menguji jenis nilai lainnya. Pola is dari contoh sebelumnya tidak terbatas pada jenis nilai yang dapat diubah ke null. Anda juga dapat menggunakan pola tersebut untuk menguji apakah variabel dari jenis referensi memiliki nilai atau merupakan null.

Contoh sebelumnya juga menunjukkan bagaimana Anda menggunakan pola jenis dalam pernyataan switch di mana variabelnya mungkin salah satu dari banyak jenis yang berbeda.

Jika Anda ingin menguji apakah suatu variabel adalah jenis tertentu, tetapi tidak menetapkannya ke variabel baru, Anda dapat menggunakan operator is dan as untuk jenis referensi dan jenis nilai yang dapat diubah ke null. Kode berikut menunjukkan cara menggunakan pernyataan is dan as yang merupakan bagian dari bahasa C# sebelum pencocokan pola diperkenalkan untuk menguji apakah suatu variabel berjenis tertentu:

// Use the is operator to verify the type.
// before performing a cast.
Giraffe g = new();
UseIsOperator(g);

// Use the as operator and test for null
// before referencing the variable.
UseAsOperator(g);

// Use pattern matching to test for null
// before referencing the variable
UsePatternMatchingIs(g);

// Use the as operator to test
// an incompatible type.
SuperNova sn = new();
UseAsOperator(sn);

// Use the as operator with a value type.
// Note the implicit conversion to int? in
// the method body.
int i = 5;
UseAsWithNullable(i);

double d = 9.78654;
UseAsWithNullable(d);

static void UseIsOperator(Animal a)
{
    if (a is Mammal)
    {
        Mammal m = (Mammal)a;
        m.Eat();
    }
}

static void UsePatternMatchingIs(Animal a)
{
    if (a is Mammal m)
    {
        m.Eat();
    }
}

static void UseAsOperator(object o)
{
    Mammal? m = o as Mammal;
    if (m is not null)
    {
        Console.WriteLine(m.ToString());
    }
    else
    {
        Console.WriteLine($"{o.GetType().Name} is not a Mammal");
    }
}

static void UseAsWithNullable(System.ValueType val)
{
    int? j = val as int?;
    if (j is not null)
    {
        Console.WriteLine(j);
    }
    else
    {
        Console.WriteLine("Could not convert " + val.ToString());
    }
}
class Animal
{
    public void Eat() => Console.WriteLine("Eating.");
    public override string ToString() => "I am an animal.";
}
class Mammal : Animal { }
class Giraffe : Mammal { }

class SuperNova { }

Seperti yang Anda lihat dengan membandingkan kode ini dengan kode pencocokan pola, sintaks pencocokan pola menyediakan fitur yang lebih kuat dengan menggabungkan pengujian dan penugasan dalam satu pernyataan. Gunakan sintaks pencocokan pola bila memungkinkan.