Aracılığıyla paylaş


Yöntem parametreleri ve değiştiricileri

Varsayılan olarak, C# bağımsız değişkenleri değere göre işlevlere geçirir. Bu yaklaşım, değişkenin bir kopyasını yöntemine geçirir. Değer (struct) türleri için yöntemi değerin bir kopyasını alır. Başvuru (class) türleri için yöntemi başvurunun bir kopyasını alır. Bağımsız değişkenleri başvuruya göre geçirmek için parametre değiştiricileri kullanabilirsiniz.

Yapı bir değer türü olduğundan, bir yapıyı bir yönteme değere göre geçirme yöntemine bağımsız değişkenin bir kopyasını gönderir. yöntemi bu kopyayla çalışır. yöntemi, çağırma yöntemindeki özgün yapıya erişemez ve bunu 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 yönteme değere göre bir başvuru türü geçirdiğinizde, yöntemi örneğe 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.

C# dili başvuru belgesi, C# dilinin en son yayımlanan sürümünü gösterir. Ayrıca, yaklaşan dil sürümü için genel önizlemelerdeki özelliklere yönelik ilk belgeleri içerir.

Belgelerde ilk olarak dilin son üç sürümünde veya geçerli genel önizlemelerde sunulan tüm özellikler tanımlanır.

Tavsiye

Bir özelliğin C# dilinde ilk tanıtıldığı zamanları bulmak için C# dil sürümü geçmişi makalesine bakın.

Değere göre geçiş ve başvuruya göre geçirme

Bu bölümdeki tüm örnekler, türler ve record türler arasındaki class farkları göstermek için aşağıdaki iki struct türü kullanır:

public record struct Point(int X, int Y);
// This doesn't use a primary constructor because the properties implemented for `record` types are 
// readonly in record class types. That would prevent the mutations necessary for this example.
public record class Point3D
{
    public int X { get; set; }
    public int Y { get; set; }
    public int Z { get; set; }
}

Aşağıdaki örneğin çıktısı, bir yapı türünü değere göre geçirme ile sınıf türünü değere göre geçirme arasındaki farkı gösterir. Her iki yöntem de Mutate bağımsız değişkenlerinin özellik değerlerini değiştirir. Parametre bir struct tür olduğunda, bu değişiklikler bağımsız değişkenin verilerinin bir kopyasını etkiler. Parametre bir class tür olduğunda, bu değişiklikler bağımsız değişkeninin başvurduğu örneği etkiler:

public class PassTypesByValue
{
    public static void Mutate(Point pt)
    {
        Console.WriteLine($"\tEnter {nameof(Mutate)}:\t\t{pt}");
        pt.X = 19;
        pt.Y = 23;

        Console.WriteLine($"\tExit {nameof(Mutate)}:\t\t{pt}");
    }
    public static void Mutate(Point3D pt)
    {
        Console.WriteLine($"\tEnter {nameof(Mutate)}:\t\t{pt}");
        pt.X = 19;
        pt.Y = 23;
        pt.Z = 42;

        Console.WriteLine($"\tExit {nameof(Mutate)}:\t\t{pt}");
    }

    public static void TestPassTypesByValue()
    {
        Console.WriteLine("===== Value Types =====");

        var ptStruct = new Point { X = 1, Y = 2 };
        Console.WriteLine($"After initialization:\t\t{ptStruct}");

        Mutate(ptStruct);

        Console.WriteLine($"After called {nameof(Mutate)}:\t\t{ptStruct}");

        Console.WriteLine("===== Reference Types =====");

        var ptClass = new Point3D { X = 1, Y = 2, Z = 3 };

        Console.WriteLine($"After initialization:\t\t{ptClass}");

        Mutate(ptClass);
        Console.WriteLine($"After called {nameof(Mutate)}:\t\t{ptClass}");

        // Output:
        // ===== Value Types =====
        // After initialization:           Point { X = 1, Y = 2 }
        //         Enter Mutate:           Point { X = 1, Y = 2 }
        //         Exit Mutate:            Point { X = 19, Y = 23 }
        // After called Mutate:            Point { X = 1, Y = 2 }
        // ===== Reference Types =====
        // After initialization:           Point3D { X = 1, Y = 2, Z = 3 }
        //         Enter Mutate:           Point3D { X = 1, Y = 2, Z = 3 }
        //         Exit Mutate:            Point3D { X = 19, Y = 23, Z = 42 }
        // After called Mutate:            Point3D { X = 19, Y = 23, Z = 42 }
    }
}

ref Değiştirici, yöntemlere başvurarak bağımsız değişkenleri geçirmenin bir yoludur. Aşağıdaki kod önceki örneği çoğaltır, ancak parametreleri başvuruya göre geçirir. Tür üzerinde struct yapılan değişiklikler, yapı başvuruyla geçirildiğinde çağırma yönteminde görünür. Başvuru türü başvuruyla geçirildiğinde anlamsal bir değişiklik olmaz:

public class PassTypesByReference
{
    public static void Mutate(ref Point pt)
    {
        Console.WriteLine($"\tEnter {nameof(Mutate)}:\t\t{pt}");
        pt.X = 19;
        pt.Y = 23;

        Console.WriteLine($"\tExit {nameof(Mutate)}:\t\t{pt}");
    }
    public static void Mutate(ref Point3D pt)
    {
        Console.WriteLine($"\tEnter {nameof(Mutate)}:\t\t{pt}");
        pt.X = 19;
        pt.Y = 23;
        pt.Z = 42;

        Console.WriteLine($"\tExit {nameof(Mutate)}:\t\t{pt}");
    }

    public static void TestPassTypesByReference()
    {
        Console.WriteLine("===== Value Types =====");

        var pStruct = new Point { X = 1, Y = 2 };
        Console.WriteLine($"After initialization:\t\t{pStruct}");

        Mutate(ref pStruct);

        Console.WriteLine($"After called {nameof(Mutate)}:\t\t{pStruct}");

        Console.WriteLine("===== Reference Types =====");

        var pClass = new Point3D { X = 1, Y = 2, Z = 3 };

        Console.WriteLine($"After initialization:\t\t{pClass}");

        Mutate(ref pClass);
        Console.WriteLine($"After called {nameof(Mutate)}:\t\t{pClass}");

        // Output:
        // ===== Value Types =====
        // After initialization:           Point { X = 1, Y = 2 }
        //         Enter Mutate:           Point { X = 1, Y = 2 }
        //         Exit Mutate:            Point { X = 19, Y = 23 }
        // After called Mutate:            Point { X = 19, Y = 23 }
        // ===== Reference Types =====
        // After initialization:           Point3D { X = 1, Y = 2, Z = 3 }
        //         Enter Mutate:           Point3D { X = 1, Y = 2, Z = 3 }
        //         Exit Mutate:            Point3D { X = 19, Y = 23, Z = 42 }
        // After called Mutate:            Point3D { X = 19, Y = 23, Z = 42 }
    }
}

Önceki örneklerde bir parametrenin özellikleri değiştirildi. Bir yöntem ayrıca bir parametreyi yeni bir değere yeniden atayabilir. Yeniden atama, değere veya başvuruya göre geçirildiğinde yapı ve sınıf türleri için farklı davranır. Aşağıdaki örnekte, değer tarafından geçirilen parametreler yeniden atandığında yapı türlerinin ve sınıf türlerinin nasıl davrandığı gösterilmektedir:

public class PassByValueReassignment
{
    public static void Reassign(Point pt)
    {
        Console.WriteLine($"\tEnter {nameof(Reassign)}:\t\t{pt}");
        pt = new Point { X = 13, Y = 29 };

        Console.WriteLine($"\tExit {nameof(Reassign)}:\t\t{pt}");
    }

    public static void Reassign(Point3D pt)
    {
        Console.WriteLine($"\tEnter {nameof(Reassign)}:\t\t{pt}");
        pt = new Point3D { X = 13, Y = 29, Z = -42 };

        Console.WriteLine($"\tExit {nameof(Reassign)}:\t\t{pt}");
    }

    public static void TestPassByValueReassignment()
    {
        Console.WriteLine("===== Value Types =====");

        var ptStruct = new Point { X = 1, Y = 2 };
        Console.WriteLine($"After initialization:\t\t{ptStruct}");

        Reassign(ptStruct);

        Console.WriteLine($"After called {nameof(Reassign)}:\t\t{ptStruct}");

        Console.WriteLine("===== Reference Types =====");

        var ptClass = new Point3D { X = 1, Y = 2, Z = 3 };

        Console.WriteLine($"After initialization:\t\t{ptClass}");

        Reassign(ptClass);
        Console.WriteLine($"After called {nameof(Reassign)}:\t\t{ptClass}");

        // Output:
        // ===== Value Types =====
        // After initialization:           Point { X = 1, Y = 2 }
        //         Enter Reassign:         Point { X = 1, Y = 2 }
        //         Exit Reassign:          Point { X = 13, Y = 29 }
        // After called Reassign:          Point { X = 1, Y = 2 }
        // ===== Reference Types =====
        // After initialization:           Point3D { X = 1, Y = 2, Z = 3 }
        //         Enter Reassign:         Point3D { X = 1, Y = 2, Z = 3 }
        //         Exit Reassign:          Point3D { X = 13, Y = 29, Z = -42 }
        // After called Reassign:          Point3D { X = 1, Y = 2, Z = 3 }
    }
}

Yukarıdaki örnekte, bir parametreyi yeni bir değere yeniden atadığınızda, türün bir değer türü veya başvuru türü olmasına bakılmaksızın bu değişikliğin çağrı yönteminden görülemediğini gösterir. Aşağıdaki örnekte, yöntemin başvuruyla aldığı bir parametreyi yeniden atadığınızda davranış gösterilmektedir:

public class PassByReferenceReassignment
{
    public static void Reassign(ref Point pt)
    {
        Console.WriteLine($"\tEnter {nameof(Reassign)}:\t\t{pt}");
        pt = new Point { X = 13, Y = 29 };

        Console.WriteLine($"\tExit {nameof(Reassign)}:\t\t{pt}");
    }

    public static void Reassign(ref Point3D pt)
    {
        Console.WriteLine($"\tEnter {nameof(Reassign)}:\t\t{pt}");
        pt = new Point3D { X = 13, Y = 29, Z = -42 };

        Console.WriteLine($"\tExit {nameof(Reassign)}:\t\t{pt}");
    }

    public static void TestPassByReferenceReassignment()
    {
        Console.WriteLine("===== Value Types =====");

        var ptStruct = new Point { X = 1, Y = 2 };
        Console.WriteLine($"After initialization:\t\t{ptStruct}");

        Reassign(ref ptStruct);

        Console.WriteLine($"After called {nameof(Reassign)}:\t\t{ptStruct}");

        Console.WriteLine("===== Reference Types =====");

        var ptClass = new Point3D { X = 1, Y = 2, Z = 3 };

        Console.WriteLine($"After initialization:\t\t{ptClass}");

        Reassign(ref ptClass);
        Console.WriteLine($"After called {nameof(Reassign)}:\t\t{ptClass}");

        // Output:
        // ===== Value Types =====
        // After initialization:           Point { X = 1, Y = 2 }
        //         Enter Reassign:         Point { X = 1, Y = 2 }
        //         Exit Reassign:          Point { X = 13, Y = 29 }
        // After called Reassign:          Point { X = 13, Y = 29 }
        // ===== Reference Types =====
        // After initialization:           Point3D { X = 1, Y = 2, Z = 3 }
        //         Enter Reassign:         Point3D { X = 1, Y = 2, Z = 3 }
        //         Exit Reassign:          Point3D { X = 13, Y = 29, Z = -42 }
        // After called Reassign:          Point3D { X = 13, Y = 29, Z = -42 }
    }
}

Yukarıdaki örnekte, başvuru tarafından geçirilen bir parametrenin değerinin yeniden atandığı çağrı bağlamında nasıl görünür olduğu gösterilmektedir.

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

Yöntemler, parametrelerin değerlerini alanlarda depolayabilir. Parametreleri değere göre geçirdiğinizde genellikle güvenlidir. yöntemi değerleri kopyalar ve yöntem bunları bir alanda depoladığı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 bildiriminde aşağıdaki değiştiricilerden birini kullanın:

  • ref: yöntemini çağırmadan önce bağımsız değişkeni başlatın. yöntemi parametresine yeni bir değer atayabilir, ancak bunun için gerekli değildir.
  • out: Yöntemini çağırmadan önce çağıran yöntemin bağımsız değişkeni başlatması gerekmez. yöntemi parametresine bir değer atamalıdır.
  • ref readonly: yöntemini çağırmadan önce bağımsız değişkeni başlatın. yöntemi parametresine yeni bir değer atayamaz.
  • in: yöntemini çağırmadan önce bağımsız değişkeni başlatın. 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.

Başvuru tarafından geçirilen parametre bir başvuru değişkenidir. Kendi değeri yoktur. Bunun yerine, başvuran adlı farklı bir değişkene başvurur. Başvuru değişkenlerini yeniden atayabilirsiniz ve bu da başvuru değişkenlerini değiştirir.

Bir sınıfın üyeleri yalnızca , , refref readonlyveya inile outfarklı imzalara sahip olamaz. Bir türün iki üyesi arasındaki tek fark bir üyenin parametresi, diğer üyenin ref ise bir , ref readonlyveya in parametresi olmasıysa outderleyici hatası oluşur. Ancak, aşağıdaki örnekte gösterildiği gibi bir yöntemin ref, ref readonly, inveya out parametresi olduğunda ve diğer yöntemde değer tarafından geçirilen bir parametre olduğunda yöntemleri aşırı yükleyebilirsiniz. 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 in değiştiricilerini ref 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şvuru 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ı üyelerinin 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 inolmadığı sürece ve struct 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. Özellikleri parametreler için ref bağımsız değişken olarak kullanamazsınız.

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

Bir parametreye ref geçirmeden önce bir bağımsız değişken başlatmanız 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;
}

Yöntem çağrısından önce bağımsız değişken olarak out geçirilen değişkenleri başlatmanız gerekmez. Ancak, çağrılan yöntemin döndürmeden önce bir değer ataması gerekir.

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.TryParsenumberdeğişkeni tanımlar.

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

Yöntem bildirimi, değiştiriciyi ref readonly gerektirir. Arama sitesindeki değiştirici isteğe bağlıdır. veya ref değiştiricisini in kullanabilirsiniz. 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 . Değişken 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 kullanarak ref 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 in değiştiricilerini ref 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.

var largeStruct = new LargeStruct { Value1 = 42, Value2 = 3.14, Value3 = "Hello" };

// Using 'in' avoids copying the large struct and prevents modification
ProcessLargeStruct(in largeStruct);
Console.WriteLine($"Original value unchanged: {largeStruct.Value1}");

// Without 'in', the struct would be copied (less efficient for large structs)
ProcessLargeStructByValue(largeStruct);
Console.WriteLine($"Original value still unchanged: {largeStruct.Value1}");

void ProcessLargeStruct(in LargeStruct data)
{
    // Can read the values
    Console.WriteLine($"Processing: {data.Value1}, {data.Value2}, {data.Value3}");
    
    // Uncomment the following line to see error CS8331
    // data.Value1 = 99; // Compilation error: cannot assign to 'in' parameter
}

void ProcessLargeStructByValue(LargeStruct data)
{
    // This method receives a copy of the struct
    Console.WriteLine($"Processing copy: {data.Value1}, {data.Value2}, {data.Value3}");
    
    // Modifying the copy doesn't affect the original
    data.Value1 = 99;
}

Değiştirici, in derleyicinin bağımsız değişken için geçici bir değişken oluşturmasını ve bu bağımsız değişkene salt okunur bir başvuru geçirmesini sağlar. 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.

Parametrelerle in yöntemler tanımlayarak performans iyileştirmesi elde edebilirsiniz. Bazı struct tür bağımsız değişkenlerin boyutu büyük olabilir ve sıkı döngülerde veya kritik kod yollarında yöntemleri çağırdığınızda, bu yapıları kopyalamanın maliyeti önemli olur. in Çağrılan yöntem bu bağımsız değişkenin durumunu değiştirmediğinden, bağımsız değişkenleri başvuruya göre güvenli bir şekilde geçirebileceğinizi belirtmek için parametreleri bildirin. 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 out bağımsız değişkenleri için ref 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 avantajı yoktur.

params Değiştirici

anahtar sözcüğüne params sahip parametre, yöntem bildirimindeki son parametre olmalıdır. Yöntem bildiriminde yalnızca bir anahtar sözcük kullanabilirsiniz params .

Parametresini params bir koleksiyon türü olarak bildirmeniz gerekir. Tanınan koleksiyon türleri şunlardır:

C# 13'e geçmeden önce, parametresi için tek boyutlu bir dizi kullanmanız gerekir.

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 bir parametreye bağımsız değişken göndermenin çeşitli yolları gösterilmektedir params .

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.

Daha fazla bilgi için C# Dil Belirtimi'ndekiBağı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.