Jump deyimleri - break, continue, returnve goto

Atlama deyimleri, denetimi koşulsuz olarak aktarır. deyimi, en yakın kapsayan yineleme deyimini veyaswitchdeyimini sonlandırır.break deyimi, en yakın kapsayan yineleme deyiminin yeni bir yinelemesini başlatır.continue deyimi, return göründüğü işlevin yürütülmesini sonlandırır ve denetimi çağırana döndürür. deyimi, goto denetimi bir etiketle işaretlenmiş bir deyime aktarır.

Özel durum oluşturan ve denetimi koşulsuz olarak aktaran deyim hakkında throw daha fazla bilgi için, Özel durum işleme deyimleri makalesinin deyim bölümü konusuna bakınthrow.

Deyimi break

deyimi, break en yakın kapsayan yineleme deyimini (, for, foreach, whileveya do döngüsü) veya switch deyimini sonlandırır. deyimi, break varsa, denetimi sonlandırılan deyimi izleyen deyime aktarır.

int[] numbers = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
foreach (int number in numbers)
{
    if (number == 3)
    {
        break;
    }

    Console.Write($"{number} ");
}
Console.WriteLine();
Console.WriteLine("End of the example.");
// Output:
// 0 1 2 
// End of the example.

İç içe döngülerde deyimi, break aşağıdaki örnekte gösterildiği gibi yalnızca onu içeren en içteki döngüyü sonlandırır:

for (int outer = 0; outer < 5; outer++)
{
    for (int inner = 0; inner < 5; inner++)
    {
        if (inner > outer)
        {
            break;
        }

        Console.Write($"{inner} ");
    }
    Console.WriteLine();
}
// Output:
// 0
// 0 1
// 0 1 2
// 0 1 2 3
// 0 1 2 3 4

deyimini bir döngü içinde switch kullandığınızda, break switch bölümünün sonundaki bir deyim denetimi yalnızca deyiminin switch dışına aktarır. Aşağıdaki örnekte gösterildiği gibi deyimini switch içeren döngü etkilenmez:

double[] measurements = [-4, 5, 30, double.NaN];
foreach (double measurement in measurements)
{
    switch (measurement)
    {
        case < 0.0:
            Console.WriteLine($"Measured value is {measurement}; too low.");
            break;

        case > 15.0:
            Console.WriteLine($"Measured value is {measurement}; too high.");
            break;

        case double.NaN:
            Console.WriteLine("Failed measurement.");
            break;

        default:
            Console.WriteLine($"Measured value is {measurement}.");
            break;
    }
}
// Output:
// Measured value is -4; too low.
// Measured value is 5.
// Measured value is 30; too high.
// Failed measurement.

Deyimi continue

deyimi, continue aşağıdaki örnekte gösterildiği gibi en yakın kapsayan yineleme deyiminin (, for, foreach, whileveya do döngüsü) yeni bir yinelemesini başlatır:

for (int i = 0; i < 5; i++)
{
    Console.Write($"Iteration {i}: ");
    
    if (i < 3)
    {
        Console.WriteLine("skip");
        continue;
    }
    
    Console.WriteLine("done");
}
// Output:
// Iteration 0: skip
// Iteration 1: skip
// Iteration 2: skip
// Iteration 3: done
// Iteration 4: done

Deyimi return

deyimi, return göründüğü işlevin yürütülmesini sonlandırır ve varsa denetimi ve işlevin sonucunu çağırana döndürür.

İşlev üyesi bir değeri hesaplamazsa, aşağıdaki örnekte gösterildiği gibi deyimini ifade olmadan kullanırsınız return :

Console.WriteLine("First call:");
DisplayIfNecessary(6);

Console.WriteLine("Second call:");
DisplayIfNecessary(5);

void DisplayIfNecessary(int number)
{
    if (number % 2 == 0)
    {
        return;
    }

    Console.WriteLine(number);
}
// Output:
// First call:
// Second call:
// 5

Yukarıdaki örnekte gösterildiği gibi, işlev üyesini return erken sonlandırmak için ifade olmadan deyimini kullanırsınız. İşlev üyesi deyimini return içermiyorsa, son deyimi yürütüldükten sonra sonlandırılır.

İşlev üyesi bir değeri hesaplarsa, aşağıdaki örnekte gösterildiği gibi deyimini return bir ifadeyle kullanırsınız:

double surfaceArea = CalculateCylinderSurfaceArea(1, 1);
Console.WriteLine($"{surfaceArea:F2}"); // output: 12.57

double CalculateCylinderSurfaceArea(double baseRadius, double height)
{
    double baseArea = Math.PI * baseRadius * baseRadius;
    double sideArea = 2 * Math.PI * baseRadius * height;
    return 2 * baseArea + sideArea;
}

deyiminin return bir ifadesi olduğunda, bu ifadenin zaman uyumsuz olmadığı sürece bir işlev üyesinin dönüş türüne örtük olarak dönüştürülebilir olması gerekir. bir async işlevden döndürülen ifadenin, işlevin dönüş türü olan veya ValueTask<TResult>türü bağımsız değişkenine Task<TResult> örtük olarak dönüştürülebilir olması gerekir. bir async işlevin dönüş türü veya ValueTaskise Task deyimini return ifade olmadan kullanırsınız.

Başvuru dönüşleri

Varsayılan olarak, return deyimi bir ifadenin değerini döndürür. Bir değişkene başvuru döndürebilirsiniz. Başvuru dönüş değerleri (veya başv dönüşleri), bir yöntemin çağırana başvuruyla döndürdüğü değerlerdir. Diğer bir ifadeyle, çağıran bir yöntem tarafından döndürülen değeri değiştirebilir ve bu değişiklik çağrılan yöntemdeki nesnenin durumuna yansıtılır. Bunu yapmak için aşağıdaki örnekte gösterildiği gibi deyimini ref anahtar sözcüğüyle birlikte kullanınreturn:

int[] xs = new int [] {10, 20, 30, 40 };
ref int found = ref FindFirst(xs, s => s == 30);
found = 0;
Console.WriteLine(string.Join(" ", xs));  // output: 10 20 0 40

ref int FindFirst(int[] numbers, Func<int, bool> predicate)
{
    for (int i = 0; i < numbers.Length; i++)
    {
        if (predicate(numbers[i]))
        {
            return ref numbers[i];
        }
    }
    throw new InvalidOperationException("No element satisfies the given condition.");
}

Başvuru dönüş değeri, bir yöntemin çağırana bir değer yerine bir değişkene başvuru döndürmesine olanak tanır. Çağıran daha sonra döndürülen değişkeni değer veya başvuruyla döndürüldü gibi ele almayı seçebilir. Çağıran, döndürülen değere başvuru olan ve başvuru yerel olarak adlandırılan yeni bir değişken oluşturabilir. Başvuru dönüş değeri, yöntemin bir değişkene başvuru (veya diğer ad) döndürdüğü anlamına gelir. Bu değişkenin kapsamı yöntemini içermelidir. Bu değişkenin ömrü, yöntemin döndürülme süresini aşmalıdır. Çağıran tarafından yöntemin dönüş değerinde yapılan değişiklikler yöntemi tarafından döndürülen değişkende yapılır.

Bir yöntemin başvuru dönüş değeri döndürdüğünü bildirmek, yöntemin bir değişkene diğer ad döndürdüğünü gösterir. Tasarım amacı genellikle kodu çağırmanın diğer ad aracılığıyla bu değişkene erişmesi ve bunu değiştirmesidir. Başvuruyla döndürülen yöntemlerin dönüş türü voidolamaz.

Çağıranın nesnenin durumunu değiştirmesi için başvuru dönüş değeri, açıkça bir başvuru değişkeni olarak tanımlanan bir değişkende depolanmalıdır.

ref Dönüş değeri, çağrılan yöntemin kapsamındaki başka bir değişkenin diğer adıdır. Başvuru dönüşünün herhangi bir kullanımını diğer adlar olarak değişkenini kullanarak yorumlayabilirsiniz:

  • Değerini atadığınızda, diğer ad verdiği değişkene bir değer atarsınız.
  • Değerini okuduğunuzda, diğer adlarına sahip olduğu değişkenin değerini okursunuz.
  • Başvuruya göre döndürürseniz, aynı değişkene bir diğer ad döndürürsün.
  • Başvuruyla başka bir yönteme geçirirseniz, diğer adlarına sahip olduğu değişkene bir başvuru geçirirsiniz.
  • Bir başvuru yerel diğer adı yaptığınızda, aynı değişken için yeni bir diğer ad oluşturursunuz.

Başvuru dönüşünü çağırma yöntemi için ref-safe-context olmalıdır. Bu da şu anlama gelir:

  • Dönüş değeri, yönteminin yürütülmesinin ötesine uzanan bir yaşam süresine sahip olmalıdır. Başka bir deyişle, bunu döndüren yönteminde yerel bir değişken olamaz. Bir sınıfın örneği veya statik alanı olabileceği gibi yöntemine geçirilen bir bağımsız değişken de olabilir. Yerel değişken döndürülmeye çalışılması, "Başvuru yerel başvurusu olmadığından başvuruyla yerel 'obj' döndürülemiyor" derleyici hatası cs8168 oluşturur.
  • Dönüş değeri değişmez değer nullolamaz. Başvuru dönüşlü bir yöntem, değeri şu anda null bir değer türü için (belirtilmemiş) değer veya null atanabilir değer türü olan bir değişkene diğer ad döndürebilir.
  • Dönüş değeri sabit, numaralandırma üyesi, bir özellikten değere göre dönüş değeri veya veya yöntemi classstructolamaz.

Ayrıca, zaman uyumsuz yöntemlerde başvuru dönüş değerlerine izin verilmez. Zaman uyumsuz bir yöntem yürütmeyi tamamlamadan önce döndürebilir, ancak dönüş değeri hala bilinmemektedir.

Başvuru dönüş değeri döndüren bir yöntem:

Aşağıdaki örnekte, bu koşulları karşılayan ve adlı pbir nesneye başvuru döndüren bir Person yöntem gösterilmektedir:

public ref Person GetContactInformation(string fname, string lname)
{
    // ...method implementation...
    return ref p;
}

Burada, hem yöntem imzasını hem de yöntem gövdesini gösteren daha eksiksiz bir başvuru dönüş örneği verilmiştir.

public static ref int Find(int[,] matrix, Func<int, bool> predicate)
{
    for (int i = 0; i < matrix.GetLength(0); i++)
        for (int j = 0; j < matrix.GetLength(1); j++)
            if (predicate(matrix[i, j]))
                return ref matrix[i, j];
    throw new InvalidOperationException("Not found");
}

Çağrılan yöntem, başvuruya göre değeri döndürmek için dönüş değerini ref readonly de bildirebilir ve çağıran kodun döndürülen değeri değiştiremeyebilir. Çağıran yöntem, değeri yerel ref readonly başvuru değişkeninde depolayarak döndürülen değeri kopyalamaktan kaçınabilir.

Aşağıdaki örnek, Title ve Authorolmak üzere iki String alanı olan bir Book sınıfı tanımlar. Ayrıca özel bir BookCollection nesne dizisi Book içeren bir sınıf tanımlar. Tek tek kitap nesneleri, yöntemini çağırarak GetBookByTitle başvuru tarafından döndürülür.


public class Book
{
    public string Author;
    public string Title;
}

public class BookCollection
{
    private Book[] books = { new Book { Title = "Call of the Wild, The", Author = "Jack London" },
                        new Book { Title = "Tale of Two Cities, A", Author = "Charles Dickens" }
                       };
    private Book nobook = null;

    public ref Book GetBookByTitle(string title)
    {
        for (int ctr = 0; ctr < books.Length; ctr++)
        {
            if (title == books[ctr].Title)
                return ref books[ctr];
        }
        return ref nobook;
    }

    public void ListBooks()
    {
        foreach (var book in books)
        {
            Console.WriteLine($"{book.Title}, by {book.Author}");
        }
        Console.WriteLine();
    }
}

Çağıran yöntem tarafından GetBookByTitle döndürülen değeri bir başvuru yerel olarak depoladığında, çağıranın dönüş değerinde yaptığı değişiklikler, aşağıdaki örnekte gösterildiği gibi nesneye BookCollection yansıtılır.

var bc = new BookCollection();
bc.ListBooks();

ref var book = ref bc.GetBookByTitle("Call of the Wild, The");
if (book != null)
    book = new Book { Title = "Republic, The", Author = "Plato" };
bc.ListBooks();
// The example displays the following output:
//       Call of the Wild, The, by Jack London
//       Tale of Two Cities, A, by Charles Dickens
//
//       Republic, The, by Plato
//       Tale of Two Cities, A, by Charles Dickens

Deyimi goto

Deyimi, goto aşağıdaki örnekte gösterildiği gibi denetimi bir etiketle işaretlenmiş bir deyime aktarır:

var matrices = new Dictionary<string, int[][]>
{
    ["A"] =
    [
        [1, 2, 3, 4],
        [4, 3, 2, 1]
    ],
    ["B"] =
    [
        [5, 6, 7, 8],
        [8, 7, 6, 5]
    ],
};

CheckMatrices(matrices, 4);

void CheckMatrices(Dictionary<string, int[][]> matrixLookup, int target)
{
    foreach (var (key, matrix) in matrixLookup)
    {
        for (int row = 0; row < matrix.Length; row++)
        {
            for (int col = 0; col < matrix[row].Length; col++)
            {
                if (matrix[row][col] == target)
                {
                    goto Found;
                }
            }
        }
        Console.WriteLine($"Not found {target} in matrix {key}.");
        continue;

    Found:
        Console.WriteLine($"Found {target} in matrix {key}.");
    }
}
// Output:
// Found 4 in matrix A.
// Not found 4 in matrix B.

Yukarıdaki örnekte gösterildiği gibi, iç içe döngüden çıkmak için deyimini goto kullanabilirsiniz.

İpucu

İç içe döngülerle çalışırken, ayrı döngüleri ayrı yöntemler halinde yeniden düzenlemeyi göz önünde bulundurun. Bu, deyimi olmadan daha basit ve daha okunabilir bir koda goto yol açabilir.

Aşağıdaki örnekte gösterildiği gibi, denetimi sabit servis talebi etiketine sahip bir switch bölümüne aktarmak için deyimindeki deyiminiswitchde kullanabilirsinizgoto:

using System;

public enum CoffeeChoice
{
    Plain,
    WithMilk,
    WithIceCream,
}

public class GotoInSwitchExample
{
    public static void Main()
    {
        Console.WriteLine(CalculatePrice(CoffeeChoice.Plain));  // output: 10.0
        Console.WriteLine(CalculatePrice(CoffeeChoice.WithMilk));  // output: 15.0
        Console.WriteLine(CalculatePrice(CoffeeChoice.WithIceCream));  // output: 17.0
    }

    private static decimal CalculatePrice(CoffeeChoice choice)
    {
        decimal price = 0;
        switch (choice)
        {
            case CoffeeChoice.Plain:
                price += 10.0m;
                break;

            case CoffeeChoice.WithMilk:
                price += 5.0m;
                goto case CoffeeChoice.Plain;

            case CoffeeChoice.WithIceCream:
                price += 7.0m;
                goto case CoffeeChoice.Plain;
        }
        return price;
    }
}

deyiminde switch , denetimi etiketli switch bölümüne aktarmak için deyimini goto default;default de kullanabilirsiniz.

Verilen ada sahip bir etiket geçerli işlev üyesinde yoksa veya deyimi etiket kapsamında değilse goto , derleme zamanı hatası oluşur. Yani, denetimi geçerli işlev üyesinin dışına veya herhangi bir iç içe geçmiş kapsama aktarmak için deyimini kullanamazsınız goto .

C# dili belirtimi

Daha fazla bilgi için C# dil belirtiminin aşağıdaki bölümlerine bakın:

Ayrıca bkz.