Yöntem Parametreleri

Varsayılan olarak, C# içindeki bağımsız değişkenler işlevlere değere göre geçirilir. Bu, değişkenin bir kopyasının yöntemine geçirildiğini gösterir. Değer (struct) türleri için yöntemine değerin bir kopyası geçirilir. Başvuru (class) türleri için, yöntemine başvurunun bir kopyası geçirilir. Parametre değiştiricileri, bağımsız değişkenleri başvuruya göre geçirmenizi sağlar. Aşağıdaki kavramlar, bu farkları ve parametre değiştiricilerinin nasıl kullanılacağını anlamanıza yardımcı olur:

  • Değere göre geçirme, değişkenin bir kopyasını yönteme geçirme anlamına gelir.
  • Başvuruya göre geçirme, değişkenine erişimi yönteme geçirme anlamına gelir.
  • Bir başvuru türü değişkeni, verilerine yönelik bir başvuru içerir.
  • Bir değer türü değişkeni verilerini doğrudan içerir.

Yapı bir değer türü olduğundan, bir yapıyı bir yönteme değere göre geçirdiğinizde yöntem yapı bağımsız değişkeninin bir kopyasını alır ve üzerinde çalışır. yönteminin çağırma yöntemindeki özgün yapıya erişimi yoktur ve bu nedenle bunu hiçbir şekilde değiştiremez. yöntemi yalnızca kopyayı değiştirebilir.

Sınıf örneği, değer türü değil başvuru türüdür. Bir başvuru türü bir yönteme değer tarafından geçirildiğinde, yöntem sınıf örneğine başvurunun bir kopyasını alır. Her iki değişken de aynı nesneye başvurur. parametresi, başvurunun bir kopyasıdır. Çağrılan yöntem, çağırma yöntemindeki örneği yeniden atayamıyor. Ancak, çağrılan yöntem örnek üyelerine erişmek için başvurunun kopyasını kullanabilir. Çağrılan yöntem bir örnek üyesini değiştirirse, çağıran yöntem aynı örneğe başvurdığından bu değişiklikleri de görür.

Aşağıdaki örneğin çıktısı farkı gösterir. yöntemi ClassTaker , sınıf örneğinin willIChange belirtilen alanını bulmak için parametresindeki adresi kullandığından alanın değerini değiştirir. willIChange Bağımsız değişkenin değeri, adresinin bir kopyası değil yapısı kopyası olduğundan, çağırma yöntemindeki yapının alanı çağrıdan StructTaker değişmez. StructTaker kopyayı değiştirir ve çağrısı StructTaker tamamlandığında kopya kaybolur.

class TheClass
{
    public string? willIChange;
}

struct TheStruct
{
    public string willIChange;
}

class TestClassAndStruct
{
    static void ClassTaker(TheClass c)
    {
        c.willIChange = "Changed";
    }

    static void StructTaker(TheStruct s)
    {
        s.willIChange = "Changed";
    }

    public static void Main()
    {
        TheClass testClass = new TheClass();
        TheStruct testStruct = new TheStruct();

        testClass.willIChange = "Not Changed";
        testStruct.willIChange = "Not Changed";

        ClassTaker(testClass);
        StructTaker(testStruct);

        Console.WriteLine("Class field = {0}", testClass.willIChange);
        Console.WriteLine("Struct field = {0}", testStruct.willIChange);
    }
}
/* Output:
    Class field = Changed
    Struct field = Not Changed
*/

Parametre türü ve bağımsız değişken modunun birleşimleri

Bağımsız değişkenin geçirilme şekli ve başvuru türü mü yoksa değer türü mü bağımsız değişkende yapılan değişikliklerin çağırandan görülemediğini denetler:

  • Değer türünü değere göre geçirdiğinizde:
    • yöntemi farklı bir nesneye başvurmak için parametresini atarsa, bu değişiklikler çağırandan görünmez.
    • yöntemi, parametresi tarafından başvuruda bulunılan nesnenin durumunu değiştirirse, bu değişiklikler çağırandan görünmez.
  • Bir başvuru türünü değere göre geçirdiğinizde:
    • yöntemi farklı bir nesneye başvurmak için parametresini atarsa, bu değişiklikler çağırandan görünmez.
    • yöntemi, parametresi tarafından başvuruda bulunılan nesnenin durumunu değiştirirse, bu değişiklikler çağırandan görünür.
  • Başvuruya göre bir değer türü geçirdiğinizde:
    • yöntemi kullanarak ref =farklı bir nesneye başvurmak için parametresini atarsa, bu değişiklikler çağırandan görünmez.
    • yöntemi, parametresi tarafından başvuruda bulunılan nesnenin durumunu değiştirirse, bu değişiklikler çağırandan görünür.
  • Başvuru türünü başvuruya göre geçirdiğinizde:
    • yöntemi farklı bir nesneye başvurmak için parametresini atarsa, bu değişiklikler çağırandan görünür.
    • yöntemi, parametresi tarafından başvuruda bulunılan nesnenin durumunu değiştirirse, bu değişiklikler çağırandan görünür.

Başvuru türünün başvuruya göre geçirilmesi, ç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. Parametresinin 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", 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("Calling method.  Name: {0}, ID: {1}\n",
        item.ItemName, item.ItemID);
}

// This method displays the following output:
// Original values in Main.  Name: Fasteners, ID: 54321
// Calling method.  Name: Stapler, ID: 12345

Başvuruların ve değerlerin güvenli bağlamı

Yöntemler, parametrelerin değerlerini alanlarda depolayabilir. Parametreler değere göre geçirildiğinde, bu genellikle güvenlidir. Değerler kopyalanır ve bir alanda depolandığında başvuru türlerine erişilebilir. Parametreleri başvuruya göre güvenli bir şekilde geçirmek için derleyicinin yeni bir değişkene başvuru atamanın ne zaman güvenli olduğunu tanımlaması gerekir. Derleyici, her ifade için bir ifadeye veya değişkene erişimi sınırlayan güvenli bir bağlam tanımlar. Derleyici iki kapsam kullanır: safe-context ve ref-safe-context.

  • Güvenli bağlam, herhangi bir ifadeye güvenli bir şekilde erişilebileceği kapsamı tanımlar.
  • ref-safe-context, herhangi bir ifadeye yapılan başvuruya güvenli bir şekilde erişilebileceği veya değiştirilebileceği kapsamı tanımlar.

Resmi olmayan bir şekilde, bu kapsamları kodunuzun artık geçerli olmayan bir başvuruya asla erişmediğinden veya başvuruyu değiştirmediğinden emin olmak için bir mekanizma olarak düşünebilirsiniz. Başvuru, geçerli bir nesneye veya yapıya başvurduğu sürece geçerlidir. Güvenli bağlam , bir değişkenin ne zaman atanabileceğini veya yeniden atanabileceğini tanımlar. ref-safe-context, bir değişkenin ne zaman başv atanabileceğini veya yeniden atanabileceğini tanımlar. Atama yeni bir değere değişken atar; başvuru ataması, değişkeni farklı bir depolama konumuna başvurmak üzere atar.

Başvuru parametreleri

Bağımsız değişkenleri değer yerine başvuruya göre geçirmek için parametre bildirimine aşağıdaki değiştiricilerden birini uygularsınız:

  • ref: yöntemi çağrılmadan önce bağımsız değişken başlatılmalıdır. yöntemi parametresine yeni bir değer atayabilir, ancak bunu yapmak için gerekli değildir.
  • out: Yöntemini çağırmadan önce bağımsız değişkeni başlatmak için çağıran yöntem gerekli değildir. yöntemi parametresine bir değer atamalıdır.
  • ref readonly: yöntemi çağrılmadan önce bağımsız değişken başlatılmalıdır. yöntemi parametresine yeni bir değer atayamaz.
  • in: yöntemi çağrılmadan önce bağımsız değişken başlatılmalıdır. yöntemi parametresine yeni bir değer atayamaz. Derleyici, parametrelere bağımsız değişkenin bir kopyasını tutmak için in geçici bir değişken oluşturabilir.

Bir sınıfın üyeleri yalnızca , , ref readonlyinveya outile reffarklı imzalara sahip olamaz. Bir türün iki üyesi arasındaki tek fark, bunlardan birinin parametresinin, diğerinin ref ise , ref readonlyveya in parametresinin olmasıysa outderleyici hatası oluşur. Ancak, aşağıdaki örnekte gösterildiği gibi bir yöntemin ref, ref readonly, inveya out parametresi, diğerinde ise değer tarafından geçirilen bir parametre olduğunda yöntemler aşırı yüklenebilir. Gizlenmesi veya geçersiz kılınması ingibi imza eşleştirmesi gerektiren diğer durumlarda , ref, ref readonlyve out imzanın bir parçasıdır ve birbiriyle eşleşmez.

Bir parametre önceki değiştiricilerden birine sahip olduğunda, ilgili bağımsız değişkenin uyumlu bir değiştiricisi olabilir:

  • Parametrenin ref bağımsız değişkeni değiştiriciyi ref içermelidir.
  • Parametrenin out bağımsız değişkeni değiştiriciyi out içermelidir.
  • Bir parametrenin in bağımsız değişkeni isteğe bağlı olarak değiştiriciyi in içerebilir. ref Bunun yerine değiştirici bağımsız değişkende kullanılıyorsa, derleyici bir uyarı yayınlar.
  • Bir parametrenin ref readonly bağımsız değişkeni veya ref değiştiricilerini in içermelidir, ancak ikisini birden içermemelidir. Hiçbir değiştirici dahil değilse, derleyici bir uyarı görüntüler.

Bu değiştiricileri kullandığınızda, bağımsız değişkenin nasıl kullanıldığını açıklar:

  • ref , yöntemin bağımsız değişkenin değerini okuyabileceği veya yazabileceği anlamına gelir.
  • out yöntemi bağımsız değişkenin değerini ayarlar anlamına gelir.
  • ref readonly yöntemi okur ancak bağımsız değişkenin değerini yazamaz anlamına gelir. Bağımsız değişken başvuruyla geçirilmelidir .
  • in yöntemi okur ancak bağımsız değişkenin değerini yazamaz anlamına gelir. Bağımsız değişken başvuruyla veya geçici bir değişken aracılığıyla geçirilir.

Önceki parametre değiştiricilerini aşağıdaki yöntem türlerinde kullanamazsınız:

Uzantı yöntemlerinin bu bağımsız değişken anahtar sözcüklerinin 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 , veya yapı olarak kısıtlanmamış genel bir structtür olmadığında, anahtar sözcüğü uzantı yönteminin ilk bağımsız değişkeninde kullanılamaz.
  • ref readonly İlk bağımsız değişken bir structolmadığı sürece ve in anahtar sözcükleri kullanılamaz.
  • ref readonly ve in anahtar sözcükleri, yapı olarak kısıtlanmış olsa bile herhangi bir genel türde kullanılamaz.

Özellikler değişken değildir. Bunlar yöntemdir. Özellikler, parametreler için ref bağımsız değişken olamaz.

ref parametre değiştirici

Parametre kullanmak ref için, aşağıdaki örnekte gösterildiği gibi hem yöntem tanımı hem de çağırma yöntemi açıkça anahtar sözcüğünü ref kullanmalıdır. (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

Parametreye geçirilen bir ref bağımsız değişkenin geçirilmeden önce başlatılması gerekir.

out parametre değiştirici

Parametre out kullanmak için hem yöntem tanımının hem de çağıran yöntemin açıkça anahtar sözcüğünü out kullanması gerekir. Örneğin:

int initializeInMethod;
OutArgExample(out initializeInMethod);
Console.WriteLine(initializeInMethod);     // value is now 44

void OutArgExample(out int number)
{
    number = 44;
}

Bağımsız değişken olarak out geçirilen değişkenlerin bir yöntem çağrısında geçirilmeden önce başlatılması gerekmez. Ancak, yöntem döndürmeden önce bir değer atamak için çağrılan yöntem gereklidir.

Deconstruct yöntemleri, birden çok değer döndürmek için değiştirici ile out parametrelerini bildirir. Diğer yöntemler birden çok dönüş değeri için değer demetleri döndürebilir.

Değişkeni bağımsız değişken olarak geçirmeden önce ayrı bir out deyimde bildirebilirsiniz. Değişkeni, ayrı bir değişken bildirimi yerine yöntem çağrısının bağımsız değişken listesinde de bildirebilirsiniz out . out değişken bildirimleri daha kompakt, okunabilir kod üretir ve ayrıca yöntem çağrısından önce değişkene yanlışlıkla bir değer atamanızı önler. Aşağıdaki örnek, Int32.TryParse yöntemi çağrısındaki değişkeni tanımlarnumber.

string numberAsString = "1640";

if (Int32.TryParse(numberAsString, out int number))
    Console.WriteLine($"Converted '{numberAsString}' to {number}");
else
    Console.WriteLine($"Unable to convert '{numberAsString}'");
// The example displays the following output:
//       Converted '1640' to 1640

Örtük olarak yazılan bir yerel değişken de bildirebilirsiniz.

ref readonly Değiştirici

Değiştirici yöntem ref readonly bildiriminde mevcut olmalıdır. Arama sitesindeki değiştirici isteğe bağlıdır. in veya ref değiştiricisi kullanılabilir. Değiştirici ref readonly , arama sitesinde geçerli değil. Çağrı sitesinde kullandığınız değiştirici bağımsız değişkenin özelliklerini açıklamaya yardımcı olabilir. Yalnızca bağımsız değişken bir değişkense ve yazılabilirse kullanabilirsiniz ref . Yalnızca bağımsız değişken bir değişken olduğunda kullanabilirsiniz in . Yazılabilir veya salt okunur olabilir. Bağımsız değişken bir değişken değilse ancak bir ifadeyse iki değiştiriciyi de ekleyemezsiniz. Aşağıdaki örneklerde bu koşullar gösterilmektedir. Aşağıdaki yöntem, performans nedenleriyle büyük bir yapının başvuruyla geçirilmesi gerektiğini belirtmek için değiştiriciyi kullanır ref readonly :

public static void ForceByRef(ref readonly OptionStruct thing)
{
    // elided
}

veya in değiştiricisini ref kullanarak yöntemini çağırabilirsiniz. Değiştiriciyi atlarsanız, derleyici bir uyarı görüntüler. Bağımsız değişken değişken değil de bir ifade olduğunda, veya ref değiştiricilerini in ekleyemezsiniz, bu nedenle uyarıyı gizlemeniz gerekir:

ForceByRef(in options);
ForceByRef(ref options);
ForceByRef(options); // Warning! variable should be passed with `ref` or `in`
ForceByRef(new OptionStruct()); // Warning, but an expression, so no variable to reference

Değişken bir readonly değişkense değiştiriciyi in kullanmanız gerekir. Bunun yerine değiştiriciyi ref kullanırsanız derleyici bir hata döndürür.

değiştirici, ref readonly yöntemin bağımsız değişkenin değişken olmayan bir ifade yerine değişken olmasını beklediğini belirtir. Değişken olmayan ifadelere örnek olarak sabitler, yöntem dönüş değerleri ve özellikler verilebilir. Bağımsız değişken bir değişken değilse, derleyici bir uyarı görüntüler.

in parametre değiştirici

in Değiştirici yöntem bildiriminde gereklidir, ancak çağrı sitesinde gereksizdir.

int readonlyArgument = 44;
InArgExample(readonlyArgument);
Console.WriteLine(readonlyArgument);     // value is still 44

void InArgExample(in int number)
{
    // Uncomment the following line to see error CS8331
    //number = 19;
}

Değiştirici, in derleyicinin bağımsız değişken için geçici bir değişken oluşturmasına ve bu bağımsız değişkene salt okunur bir başvuru geçirmesine olanak tanır. Bağımsız değişkenin dönüştürülmesi gerektiğinde, bağımsız değişken türünden örtük bir dönüştürme olduğunda veya bağımsız değişken değişken olmayan bir değer olduğunda, derleyici her zaman geçici bir değişken oluşturur. Örneğin, bağımsız değişken değişmez değer olduğunda veya özellik erişimcisinden döndürülen değer olduğunda. API'niz bağımsız değişkenin başvuruya göre geçirilmesini gerektirdiğinde ref readonly , değiştirici yerine değiştiriciyi in seçin.

Parametreler kullanılarak in tanımlanan yöntemler potansiyel olarak performans iyileştirmesi elde eder. Bazı struct tür bağımsız değişkenlerin boyutu büyük olabilir ve yöntemler sıkı döngülerde veya kritik kod yollarında çağrıldığında, bu yapıları kopyalamanın maliyeti önemli olur. Yöntemler, bağımsız değişkenlerin başvuru tarafından güvenle geçirilebileceğini belirtmek için parametreleri bildirir in çünkü çağrılan yöntem bu bağımsız değişkenin durumunu değiştirmez. Bu bağımsız değişkenleri başvuruya göre geçirmek(potansiyel olarak) pahalı kopyayı önler. Bağımsız değişkenin in değere göre değil başvuruya göre geçirildiğinden emin olmak için arama sitesine değiştiriciyi açıkça eklersiniz. Açıkça kullanarak in aşağıdaki iki etkiye sahiptir:

  • Çağrı sitesinde belirtilmesi in , derleyiciyi eşleşen in parametreyle tanımlanan bir yöntemi seçmeye zorlar. Aksi takdirde, iki yöntem yalnızca varlığında infarklılık gösterdiğinde, değere göre aşırı yükleme daha iyi bir eşleşmedir.
  • belirterek in, başvuruya göre bir bağımsız değişken geçirme amacınızı bildirirsiniz. ile in kullanılan bağımsız değişken, doğrudan başvurulabilen bir konumu temsil etmelidir. ve ref bağımsız değişkenleri için out aynı genel kurallar geçerlidir: Sabitleri, normal özellikleri veya değer üreten diğer ifadeleri kullanamazsınız. Aksi takdirde, çağrı sitesinde atlanması in derleyiciye yönteme salt okunur başvuru ile geçici bir değişken oluşturmanın uygun olduğunu bildirir. Derleyici, bağımsız değişkenlerle in çeşitli kısıtlamaların üstesinden gelmek için geçici bir değişken oluşturur:
    • Geçici değişken, derleme zamanı sabitlerini parametre olarak in sağlar.
    • Geçici değişken, parametreler için in özelliklere veya diğer ifadelere izin verir.
    • Geçici değişken, bağımsız değişken türünden parametre türüne örtük dönüştürmenin olduğu bağımsız değişkenlere izin verir.

Yukarıdaki tüm örneklerde, derleyici sabit, özellik veya başka bir ifadenin değerini depolayan geçici bir değişken oluşturur.

Aşağıdaki kodda bu kurallar gösterilmektedir:

static void Method(in int argument)
{
    // implementation removed
}

Method(5); // OK, temporary variable created.
Method(5L); // CS1503: no implicit conversion from long to int
short s = 0;
Method(s); // OK, temporary int created with the value 0
Method(in s); // CS1503: cannot convert from in short to in int
int i = 42;
Method(i); // passed by readonly reference
Method(in i); // passed by readonly reference, explicitly using `in`

Şimdi, değere göre bağımsız değişkenleri kullanan başka bir yöntemin kullanılabilir olduğunu varsayalım. Sonuçlar aşağıdaki kodda gösterildiği gibi değişir:

static void Method(int argument)
{
    // implementation removed
}

static void Method(in int argument)
{
    // implementation removed
}

Method(5); // Calls overload passed by value
Method(5L); // CS1503: no implicit conversion from long to int
short s = 0;
Method(s); // Calls overload passed by value.
Method(in s); // CS1503: cannot convert from in short to in int
int i = 42;
Method(i); // Calls overload passed by value
Method(in i); // passed by readonly reference, explicitly using `in`

Bağımsız değişkenin başvuruyla geçirildiği tek yöntem çağrısı, son çağrıdır.

Not

Önceki kod basitlik için bağımsız değişken türü olarak kullanır int . int Çoğu modern makinede başvurudan büyük olmadığından, tek int bir başvurudan salt okunur başvuru geçirmenin bir yararı yoktur.

params Değiştirici

Yöntem bildiriminde anahtar sözcüğünden params sonra başka parametreye izin verilmez ve yöntem bildiriminde yalnızca params bir anahtar sözcük kullanılabilir.

Parametrenin params bildirilen türü bir koleksiyon türü olmalıdır. Tanınan koleksiyon türleri şunlardır:

C# 13'e geçmeden önce parametresi tek boyutlu bir dizi olmalıdır.

Parametresi olan params bir yöntemi çağırdığınızda şunları geçirebilirsiniz:

  • Dizi öğelerinin türündeki bağımsız değişkenlerin virgülle ayrılmış listesi.
  • Belirtilen türdeki bağımsız değişkenler koleksiyonu.
  • Bağımsız değişken yok. Bağımsız değişken göndermezseniz, listenin params uzunluğu sıfır olur.

Aşağıdaki örnekte bağımsız değişkenlerin bir params parametreye gönderilebileceği çeşitli yollar gösterilmektedir.

public static void ParamsModifierExample(params int[] list)
{
    for (int i = 0; i < list.Length; i++)
    {
        System.Console.Write(list[i] + " ");
    }
    System.Console.WriteLine();
}

public static void ParamsModifierObjectExample(params object[] list)
{
    for (int i = 0; i < list.Length; i++)
    {
        System.Console.Write(list[i] + " ");
    }
    System.Console.WriteLine();
}

public static void TryParamsCalls()
{
    // You can send a comma-separated list of arguments of the
    // specified type.
    ParamsModifierExample(1, 2, 3, 4);
    ParamsModifierObjectExample(1, 'a', "test");

    // A params parameter accepts zero or more arguments.
    // The following calling statement displays only a blank line.
    ParamsModifierObjectExample();

    // An array argument can be passed, as long as the array
    // type matches the parameter type of the method being called.
    int[] myIntArray = { 5, 6, 7, 8, 9 };
    ParamsModifierExample(myIntArray);

    object[] myObjArray = { 2, 'b', "test", "again" };
    ParamsModifierObjectExample(myObjArray);

    // The following call causes a compiler error because the object
    // array cannot be converted into an integer array.
    //ParamsModifierExample(myObjArray);

    // The following call does not cause an error, but the entire
    // integer array becomes the first element of the params array.
    ParamsModifierObjectExample(myIntArray);
}
/*
Output:
    1 2 3 4
    1 a test

    5 6 7 8 9
    2 b test again
    System.Int32[]
*/

Bir parametrenin bağımsız değişkeni params bir koleksiyon türü olduğunda aşırı yükleme çözümlemesi belirsizliğe neden olabilir. Bağımsız değişkenin koleksiyon türü, parametrenin koleksiyon türüne dönüştürülebilir olmalıdır. Farklı aşırı yüklemeler bu parametre için daha iyi dönüştürmeler sağladığında, bu yöntem daha iyi olabilir. Ancak, parametrenin params bağımsız değişkeni ayrık öğelerse veya eksikse, farklı params parametre türlerine sahip tüm aşırı yüklemeler bu parametre için eşittir.

Diğer ayrıntılar için C# Dil Belirtimi'ndeki Bağımsız Değişken listelerindeki bölüme bakın. Dil belirtimi, C# sözdizimi ve kullanımı için kesin bir kaynaktır.