Jump deyimleri - break
, continue
, return
ve goto
Atlama deyimleri, denetimi koşulsuz olarak aktarır. deyimi, en yakın kapsayan yineleme deyimini veyaswitch
deyimini 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
, while
veya 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
, while
veya 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ü void
olamaz.
Ç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
null
olamaz. Başvuru dönüşlü bir yöntem, değeri şu andanull
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
class
struct
olamaz.
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:
- dönüş türünün önüne ref anahtar sözcüğünü ekleyin.
- Yöntem gövdesindeki her return deyimi, döndürülen örneğin adının önünde ref anahtar sözcüğünü içerir.
Aşağıdaki örnekte, bu koşulları karşılayan ve adlı p
bir 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 Author
olmak ü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 deyiminiswitch
de 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: