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.
  • Bildirimdestruct, veya readonly ref structbildirmek ref struct için. Daha fazla bilgi için ref struct makalesine bakın.
  • Bildirimde ref struct , bir alanın bir başvuru olduğunu bildirmek için. Alan makalesine ref 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 , inveya outile reffarklı 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 outhatası 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 refbir , inveya 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ı ingibi imza eşleştirmesi gerektiren diğer durumlarda, refve 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 , inve 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. Anahtar in 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 bir return 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 refdö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ı GetEstimatedValuebir 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 refkullanı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 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 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.

Ayrıca bkz.