ref (C# Başvurusu)
anahtar ref
sözcüğü, bir değişkenin bir başvuru veya başka bir nesnenin diğer adı olduğunu gösterir. Beş farklı bağlamda kullanılır:
- Bir yöntem imzasında ve yöntem çağrısında, bir bağımsız değişkeni başvuruya göre yönteme geçirmek için. Daha fazla bilgi için bkz. Bağımsız değişkeni başvuruya göre geçirme.
- Bir yöntem imzasında, başvuruya göre çağırana bir değer döndürmek için. Daha fazla bilgi için bkz . Başvuru dönüş değerleri.
- Bir üye gövdesinde, bir başvuru dönüş değerinin çağıranın değiştirmek istediği bir başvuru olarak yerel olarak depolandığını belirtmek için. Alternatif olarak, bir yerel değişkenin başvuruyla başka bir değere eriştiği belirtebilirsiniz. Daha fazla bilgi için bkz . Ref locals.
- Bildirimde
struct
, veyareadonly ref struct
bildirmekref struct
için. Daha fazla bilgi içinref struct
makalesine bakın. - Bildirimde
ref struct
, bir alanın bir başvuru olduğunu bildirmek için. Alan makalesineref
bakın.
Başvuruya göre bağımsız değişken geçirme
Bir yöntemin parametre listesinde kullanıldığında, ref
anahtar sözcüğü bir bağımsız değişkenin değere göre değil başvuruya göre geçirildiğini gösterir. anahtar ref
sözcüğü, resmi parametreyi değişken olması gereken bağımsız değişken için bir diğer ad yapar. Başka bir deyişle, parametredeki herhangi bir işlem bağımsız değişkende yapılır.
Örneğin, çağıranın bir yerel değişken ifadesi veya dizi öğesi erişim ifadesi geçtiğini varsayalım. Çağrılan yöntem daha sonra başv parametresinin başvurduğu nesneyi değiştirebilir. Bu durumda, çağıranın yerel değişkeni veya dizi öğesi, yöntem döndürdüğünde yeni nesneye başvurur.
Not
Başvuruya göre geçirme kavramını başvuru türleri kavramıyla karıştırmayın. İki kavram aynı değildir. Yöntem parametresi, değer türünden veya başvuru türünden bağımsız olarak değiştirilebilir ref
. Başvuru tarafından geçirildiğinde değer türünde kutulama yoktur.
Parametre ref
kullanmak için, aşağıdaki örnekte gösterildiği gibi hem yöntem tanımının hem de çağırma yönteminin açıkça anahtar sözcüğünü ref
kullanması gerekir. (Com çağrısı yapılırken çağıran yöntemin atlanabilir ref
olması dışında.)
void Method(ref int refArgument)
{
refArgument = refArgument + 44;
}
int number = 1;
Method(ref number);
Console.WriteLine(number);
// Output: 45
Bir veya in
parametresine geçirilen bir ref
bağımsız değişkenin geçirilmeden önce başlatılması gerekir. Bu gereksinim, bağımsız değişkenlerinin geçirilmeden önce açıkça başlatılması gerekmeyen out parametrelerinden farklıdır.
Bir sınıfın üyeleri yalnızca , in
veya out
ile ref
farklı imzalara sahip olamaz. Bir türün iki üyesi arasındaki tek fark, bunlardan birinin parametresinin, diğerinin ise bir ref
veya in
parametresinin olmasıysa derleyici out
hatası oluşur. Örneğin aşağıdaki kod derlenemez.
class CS0663_Example
{
// Compiler error CS0663: "Cannot define overloaded
// methods that differ only on ref and out".
public void SampleMethod(out int i) { }
public void SampleMethod(ref int i) { }
}
Ancak, aşağıdaki örnekte gösterildiği gibi bir yöntemin ref
bir , in
veya out
parametresi ve diğerinde değer tarafından geçirilen bir parametre olduğunda yöntemler aşırı yüklenebilir.
class RefOverloadExample
{
public void SampleMethod(int i) { }
public void SampleMethod(ref int i) { }
}
Gizlenmesi veya geçersiz kılınması in
gibi imza eşleştirmesi gerektiren diğer durumlarda, ref
ve out
imzanın bir parçasıdır ve birbiriyle eşleşmez.
Özellikler değişken değildir. Bunlar yöntemdir ve parametrelere ref
geçirilemiyor.
Aşağıdaki yöntem türleri için , in
ve out
anahtar sözcüklerini kullanamazsınızref
:
- Zaman uyumsuz değiştiriciyi kullanarak tanımladığınız zaman uyumsuz yöntemler.
- Verim dönüşünü veya
yield break
deyimini içeren yineleyici yöntemleri.
uzantı yöntemlerinin şu anahtar sözcüklerin kullanımıyla ilgili kısıtlamaları da vardır:
- Anahtar
out
sözcüğü, bir uzantı yönteminin ilk bağımsız değişkeninde kullanılamaz. - Bağımsız
ref
değişken bir yapı olmadığında veya yapı olması kısıtlanmamış genel bir tür olduğunda, uzantı yönteminin ilk bağımsız değişkeninde anahtar sözcüğü kullanılamaz. in
İlk bağımsız değişken bir yapı olmadığı sürece anahtar sözcüğü kullanılamaz. Anahtarin
sözcük, yapı olarak kısıtlanmış olsa bile herhangi bir genel türde kullanılamaz.
Başvuruya göre bağımsız değişken geçirme: Örnek
Önceki örneklerde değer türleri başvuruya göre geçirildi. Başvuru türlerini başvuruya göre geçirmek için anahtar sözcüğünü ref
de kullanabilirsiniz. Başvuru türünü başvuruya göre geçirmek, çağrılan yöntemin, başvuru parametresinin çağıranda başvurduğu nesneyi değiştirmesini sağlar. Nesnesinin depolama konumu, başvuru parametresinin değeri olarak yöntemine geçirilir. Parametrenin depolama konumundaki değeri değiştirirseniz (yeni bir nesneye işaret etmek için), çağıranın başvurduğu depolama konumunu da değiştirirsiniz. Aşağıdaki örnek, başvuru türünün bir örneğini parametre olarak ref
geçirir.
class Product
{
public Product(string name, int newID)
{
ItemName = name;
ItemID = newID;
}
public string ItemName { get; set; }
public int ItemID { get; set; }
}
private static void ChangeByReference(ref Product itemRef)
{
// Change the address that is stored in the itemRef parameter.
itemRef = new Product("Stapler", 99999);
// You can change the value of one of the properties of
// itemRef. The change happens to item in Main as well.
itemRef.ItemID = 12345;
}
private static void ModifyProductsByReference()
{
// Declare an instance of Product and display its initial values.
Product item = new Product("Fasteners", 54321);
System.Console.WriteLine("Original values in Main. Name: {0}, ID: {1}\n",
item.ItemName, item.ItemID);
// Pass the product instance to ChangeByReference.
ChangeByReference(ref item);
System.Console.WriteLine("Back in Main. Name: {0}, ID: {1}\n",
item.ItemName, item.ItemID);
}
// This method displays the following output:
// Original values in Main. Name: Fasteners, ID: 54321
// Back in Main. Name: Stapler, ID: 12345
Başvuru türlerini değere ve başvuruya göre geçirme hakkında daha fazla bilgi için bkz. Reference-Type Parametreleri Geçirme.
Başvuru dönüş değerleri
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.
Başvuru dönüş değeri anahtar sözcüğü kullanılarak ref
tanımlanır:
- Yöntem imzasında. Örneğin, aşağıdaki yöntem imzası yöntemin başvuruya
GetCurrentPrice
göre bir Decimal değer döndürdüğünü gösterir.
public ref decimal GetCurrentPrice()
- belirteci
return
ile yöntemindeki birreturn
deyimde döndürülen değişken arasında. Örnek:
return ref DecimalArray[0];
Çağıranın nesnenin durumunu değiştirebilmesi için başvuru dönüş değerinin ref yerel olarak açıkça tanımlanan bir değişkende depolanması gerekir.
Burada hem yöntem imzasını hem de yöntem gövdesini gösteren daha eksiksiz bir başv 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 başvuru salt okunur değişkeninde depolayarak döndürülen değerin kopyalanmasını önleyebilir.
Örnek için bkz. Başv dönüşleri ve başv yerel ayarları örneği.
Başvuru yerel öğeleri
kullanılarak return ref
döndürülen değerlere başvurmak için başvuru yerel değişkeni kullanılır. Başv yerel değişkeni başv olmayan bir dönüş değerine başlatılamaz. Başka bir deyişle, başlatmanın sağ tarafı bir başvuru olmalıdır. Başvuru yerel değeri üzerinde yapılan tüm değişiklikler, yöntemi başvuruya göre değeri döndüren nesnenin durumuna yansıtılır.
İki yerde anahtar sözcüğünü ref
kullanarak yerel başvuru tanımlarsınız:
- Değişken bildiriminden önce.
- Başvuruya göre değeri döndüren yöntem çağrısından hemen önce.
Örneğin, aşağıdaki deyim adlı GetEstimatedValue
bir yöntem tarafından döndürülen bir başv yerel değerini tanımlar:
ref decimal estValue = ref Building.GetEstimatedValue();
Bir değere başvuruyla aynı şekilde erişebilirsiniz. Bazı durumlarda, bir değere başvuruyla erişmek, pahalı olabilecek kopyalama işleminden kaçınarak performansı artırır. Örneğin, aşağıdaki deyim bir değere başvurmak için kullanılan bir başvuru yerel değişkeninin nasıl tanımlandığını gösterir.
ref VeryLargeStruct reflocal = ref veryLargeStruct;
Her iki örnekte de anahtar sözcüğün ref
her iki yerde de kullanılması gerekir veya derleyici CS8172 "Bir değerle başvuruya göre değişken başlatılamıyor" hatasını oluşturur.
deyiminin foreach
yineleme değişkeni bir başv yerel veya başvuru salt okunur yerel değişkeni olabilir. Daha fazla bilgi için foreach deyimi makalesine bakın. Ref atama işleciyle ref yerel veya ref salt okunur yerel değişkenini yeniden atayabilirsiniz.
Salt okunur yereller için başvuru
Salt okunur yerel başvuru, imzasında bulunan ref readonly
ve kullanan bir yöntem veya özellik tarafından döndürülen değerlere başvurmak için return ref
kullanılır. Değişken ref readonly
, yerel değişkenin ref
özelliklerini bir değişkenle birleştirir readonly
: atandığı depolama alanının diğer adıdır ve değiştirilemez.
Başv dönüşleri ve başv yerel ayarları örneği
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 başvuruyla döndürülür GetBookByTitle
.
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 nesnesine 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
başvuru alanları
Türlerde ref struct
, alan olan ref
alanları bildirebilirsiniz. ref
alanları yalnızca başvurunun başvurduğu nesneden uzun yaşamadığından emin olmak için türlerde ref struct
geçerlidir. Bu özellik, gibi System.Span<T>türleri etkinleştirir:
public readonly ref struct Span<T>
{
internal readonly ref T _reference;
private readonly int _length;
// Omitted for brevity...
}
Türü, Span<T>
ardışık öğelere eriştiği bir başvuruyu depolar. Başvuru, nesnenin Span<T>
başvurduğu depolama alanının kopyalarını yapmaktan kaçınmasını sağlar.
C# dili belirtimi
Daha fazla bilgi edinmek için, bkz. C# Dil Belirtimi. Dil belirtimi, C# sözdizimi ve kullanımı için kesin bir kaynaktır.