Desen eşleştirme ve is ve işleçleri kullanarak güvenli bir şekilde atama

Nesneler çok biçimli olduğundan, temel sınıf türü değişkeninin türetilmiş bir türü barındırması mümkündür. Türetilmiş türün örnek üyelerine erişmek için değeri türetilmiş türe geri döndürmek gerekir. Ancak, bir atama bir oluşturma InvalidCastExceptionriski oluşturur. C# yalnızca başarılı olduğunda koşullu olarak atama gerçekleştiren desen eşleştirme deyimleri sağlar. C# ayrıca bir değerin belirli bir türde olup olmadığını test etmek için is ve işleçlerini de sağlar.

Aşağıdaki örnekte desen eşleştirme is deyiminin nasıl kullanılacağı gösterilmektedir:

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 { }

Yukarıdaki örnekte desen eşleştirme söz diziminin birkaç özelliği gösterilmektedir. deyimi, if (a is Mammal m) testi bir başlatma atamasıyla birleştirir. Atama yalnızca test başarılı olduğunda gerçekleşir. değişkeni m yalnızca atanmış olduğu katıştırılmış if deyiminin kapsamındadır. Daha sonra aynı yöntemde erişemezsiniz m . Yukarıdaki örnekte, bir nesneyi belirtilen türe dönüştürmek için işlecinin as nasıl kullanılacağı da gösterilmektedir.

Aşağıdaki örnekte gösterildiği gibi, null atanabilir bir değer türünün değeri varsa test için de aynı söz dizimini kullanabilirsiniz:

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;
    }
}

Yukarıdaki örnekte, dönüştürmelerle kullanılacak desen eşleştirmesinin diğer özellikleri gösterilmektedir. Özellikle değeri denetleyerek null desen için null bir değişkeni test edebilirsiniz. değişkeninin çalışma zamanı değeri olduğunda null, tür denetimi yapılan bir is deyim her zaman döndürür false. Desen eşleştirme is deyimi veya Nullable<int>gibi int? null atanabilir bir değer türüne izin vermez, ancak başka herhangi bir değer türünü test edebilirsiniz. is Önceki örnekteki desenler null atanabilir değer türleriyle sınırlı değildir. Bu desenleri, bir başvuru türü değişkeninin değeri olup olmadığını veya değeri olup olmadığını nulltest etmek için de kullanabilirsiniz.

Yukarıdaki örnek, değişkenin birçok farklı türden biri olabileceği bir switch deyimde tür desenini nasıl kullandığınızı da gösterir.

Bir değişkenin belirli bir tür olup olmadığını test etmek, ancak bunu yeni bir değişkene atamak istemiyorsanız, başvuru türleri ve null atanabilir değer türleri için ve as işleçlerini kullanabilirsinizis. Aşağıdaki kod, bir değişkenin is belirli bir türde olup olmadığını test etmek için desen eşleştirme kullanılmadan önce C# dilinin parçası olan ve as deyimlerinin nasıl kullanılacağını gösterir:

// 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 { }

Bu kodu desen eşleştirme koduyla karşılaştırarak görebileceğiniz gibi, desen eşleştirme söz dizimi testi ve atamayı tek bir deyimde birleştirerek daha sağlam özellikler sağlar. Mümkün olduğunda desen eşleştirme söz dizimini kullanın.