Not
Bu sayfaya erişim yetkilendirme gerektiriyor. Oturum açmayı veya dizinleri değiştirmeyi deneyebilirsiniz.
Bu sayfaya erişim yetkilendirme gerektiriyor. Dizinleri değiştirmeyi deneyebilirsiniz.
Not
Bu makale bir özellik belirtimidir. Belirtim, özelliğin tasarım belgesi olarak görev alır. Önerilen belirtim değişikliklerini ve özelliğin tasarımı ve geliştirilmesi sırasında gereken bilgileri içerir. Bu makaleler, önerilen belirtim değişiklikleri son haline getirilene ve geçerli ECMA belirtimine dahil edilene kadar yayımlanır.
Özellik belirtimi ile tamamlanan uygulama arasında bazı tutarsızlıklar olabilir. Bu farklılıklar, ilgili dil tasarım toplantısı (LDM) notlarındakaydedilir.
Özellik belirtimlerini C# dil standardına benimseme işlemi hakkında daha fazla bilgi edinmek için
Şampiyon sorunu: https://github.com/dotnet/csharplang/issues/6010
Özet
Parametre bildirim yeri değiştiricisi ref readonly iznine izin ver ve çağrı yeri kurallarını aşağıdaki gibi değiştir:
| Çağrı yeri açıklaması |
ref parametresi |
ref readonly parametresi |
in parametresi |
out parametresi |
|---|---|---|---|---|
ref |
Izin verilen | İzin Verilen | Uyarı | Hata |
in |
Hata | İzin Verilen | Izin verilen | Hata |
out |
Hata | Hatası | Hata | Izin verilen |
| Ek açıklama yok | Hata | Uyarı | Izin verilen | Hata |
(Mevcut kurallarda bir değişiklik olduğuna dikkat edin: in parametresi ref çağrı sitesi ek açıklamasıyla hata yerine uyarı üretir.)
Başvuru değeri kurallarını aşağıdaki gibi değiştirin:
| Değer türü |
ref parametresi |
ref readonly parametresi |
in parametresi |
out parametresi |
|---|---|---|---|---|
| rvalue | Hata | Uyarı | Izin verilen | Hata |
| lvalue | Izin verilen | İzin Verilen | Izin verilen | Izin verilen |
Burada lvalue bir değişken (yani konumu olan bir değer; yazılabilir/atanabilir olması gerekmez) ve rvalue herhangi bir değer türü anlamına gelir.
Motivasyon
C# 7.2 , salt okunur referansları geçirmek için in olarak parametreleri tanıttı.
in parametreleri hem lvalue'lara hem de rvalue'lara izin verir ve çağrı alanında ek açıklama olmadan kullanılabilir.
Ancak, parametrelerinden başvuruları yakalayan veya döndüren API'ler, rvalue’lara izin vermemek ve çağrı yerinde bir başvurunun yakalandığını belirtecek bazı göstergeler zorunlu kılmak istemektedir.
ref readonly parametreleri, rvalue'larla veya çağrı alanında ek açıklama olmadan kullanıldığında uyarı vermeleri gibi durumlarda idealdir.
Ayrıca, sadece salt okunur başvurulara ihtiyaç duyan ve bu şekilde kullanan API’ler de vardır.
-
refparametreler,inkullanılmaya başlanmadan önce tanıtıldığından vein'ye geçiş kaynak ve ikili uyumsuzluğa yol açabilecek bir değişiklik olacağından, örneğinQueryInterfaceveya -
inparametreleri, rvalue nesneleri onlara aktarmanın pek mantıklı olmadığı durumlarda bile salt okunur referansları kabul etmek içinReadOnlySpan<T>..ctor(in T value)veya - Gönderilen referansı değiştirmeseler bile, rvalue'ları kabul etmeyen
refparametreleri, örneğinUnsafe.IsNullRef.
Bu API'ler kullanıcıları bölmeden ref readonly parametrelerine geçiş yapabilir.
İkili uyumluluk hakkında ayrıntılı bilgi için bkz. önerilen meta veri kodlama.
Özellikle, değiştirme
-
ref→ref readonlyyalnızca sanal yöntemler için ikili uyumsuzluğa yol açacak bir değişiklik olabilir. -
ref→in, sanal yöntemler için ikili uyum bozucu değişiklik olur, ancak kaynak uyum bozucu değişiklik olmaz (çünkü kurallar, yalnızcarefparametrelere geçirileninbağımsız değişkenler için uyarı verecek şekilde değişir), -
in→ref readonlybüyük bir değişiklik olmayacaktır (ancak çağrı noktası açıklaması veya rvalue bir uyarıya yol açmaz).- Eski derleyici sürümlerini kullanan kullanıcılar için, bu bir kaynak uyumsuzluğu değişikliği olacaktır (çünkü
ref readonlyparametrelerinirefparametresi olarak yorumlayıp çağrı yerindein'yi veya açıklama vermeden işlem yapmaya izin vermezler) veLangVersion <= 11olan yeni derleyici sürümleri için tutarlılık sağlamak amacıyla, ilgili bağımsız değişkenlerref readonlydeğiştiricisi ile geçilmediği sürecerefparametrelerin desteklenmeyeceğine dair bir hata iletisi verilecektir. Bunu unutmayın.
- Eski derleyici sürümlerini kullanan kullanıcılar için, bu bir kaynak uyumsuzluğu değişikliği olacaktır (çünkü
Ters yönde, değişen
-
ref readonly→refpotansiyel olarak kaynak kodda bozucu bir değişiklik olabilir (yalnızcarefçağrı sitesi ek açıklaması kullanılmışsa ve yalnızca bağımsız değişkenlerde salt okunur başvurular kullanılmışsa) ve sanal yöntemler için ikili uyumluluğu bozabilecek bir değişiklik olabilir. -
ref readonly→inkesici değişiklik olmaz (ancakrefçağrı noktası ek açıklaması uyarıya neden olur).
Yukarıda açıklanan kuralların yöntem imzaları için geçerli olduğunu, ancak temsilci imzaları için geçerli olmadığını unutmayın.
Örneğin, bir temsilci imzasında ref'ın in olarak değiştirilmesi, kaynak kırıcı bir değişiklik olabilir (eğer bir kullanıcı bu temsilci türüne ref parametresine sahip bir yöntem atıyorsa, bu, API değişikliğinden sonra bir hata haline gelir).
Ayrıntılı tasarım
Genel olarak, bu teklifte açıkça değiştirilenler dışında,
Parametre bildirimleri
Dil bilgisi değişiklikleri gerekmez.
Parametreler için ref readonly değiştiricisine izin verilecek.
Normal yöntemlerin dışında, dizin oluşturucu parametreleri (ref readonly gibi ancak inaksine) için ref izin verilir, ancak işleç parametreleri için izin verilmez (ref ancak inaksine).
ref readonly parametreleri için varsayılan parametre değerlerine bir uyarı ile izin verilir, çünkü bunlar rvalue'ları geçmeye eşdeğerdir.
Bu, API yazarlarının varsayılan değerlere sahip in parametreleri kaynak hatalarına neden olmadan ref readonly parametrelerle değiştirmesine olanak tanır.
Değer tipine yönelik denetimler
ref parametreleri için ref readonly bağımsız değişken değiştiriciye izin verilse de, bunun değer türü denetimlerini etkilemediğini unutmayın, yani örneğin,
-
refyalnızca atanabilir değerlerle kullanılabilir; - Salt-okunur başvuruları iletmek için bunun yerine
inbağımsız değişken değiştiricisini kullanmak gerekir. - rvalue'ları geçirmek için hiçbir değiştirici kullanmamak gerekir (bu,
ref readonlyaçıklandığı gibi, parametreleri için uyarıya yol açar).
Aşırı yükleme çözümü
Aşırı yükleme çözümlemesi,bu teklifin özetini in parametresine sahip yöntemlerin çağrıları, refolarak işaretlenmiş karşılık gelen bağımsız değişkenle eşleştirecek şekilde mevcut davranışta bir değişiklik meydana geldi; bu değişiklik LangVersion üzerinden sınırlandırılacaktır.
Ancak, ref readonly parametresine çağrı sitesi değiştiricisi olmayan bir bağımsız değişken geçirildiğinde verilen uyarı, parametrenin belirli bir koşulu karşılaması durumunda gizlenir.
- bir uzantı yöntemi çağırmasında alıcı,
- özel koleksiyon başlatıcı veya interpolasyonlu dize işleyicisinin bir parçası olarak örtük olarak kullanılır.
Değere göre aşırı yüklemeler, bağımsız değişken değiştiricisi olmaması durumunda (ref readonly parametrelerin aynı davranışa sahip olması) in aşırı yüklemeler yerine tercih edilir.
Yöntem dönüştürmeleri
Benzer şekilde, anonim işlevin [§10.7] ve yöntem grubu [§10.8] dönüştürmeleri için bu değiştiriciler uyumlu olarak kabul edilir (ancak farklı değiştiriciler arasında izin verilen dönüştürmeler uyarıyla sonuçlanıyor):
- Hedef yöntemin
ref readonlyparametresinin temsilcinininveyarefparametresiyle eşleşmesine izin verilir. - Hedef yöntemin
inparametresinin, temsilcininref readonlyparametresiyle eşleşmesine veya dil sürümüne bağlı olarakrefparametresiyle eşleşmesine izin verilir. - Not: Hedef yöntemin
refparametresi temsilcinininveyaref readonlyparametresiyle eşleşmesine izin verilmez.
Örneğin:
DIn dIn = (ref int p) => { }; // error: cannot match `ref` to `in`
DRef dRef = (in int p) => { }; // warning: mismatch between `in` and `ref`
DRR dRR = (ref int p) => { }; // error: cannot match `ref` to `ref readonly`
dRR = (in int p) => { }; // warning: mismatch between `in` and `ref readonly`
dIn = (ref readonly int p) => { }; // warning: mismatch between `ref readonly` and `in`
dRef = (ref readonly int p) => { }; // warning: mismatch between `ref readonly` and `ref`
delegate void DIn(in int p);
delegate void DRef(ref int p);
delegate void DRR(ref readonly int p);
İmza eşleştirme
Tek bir türde bildirilen üyeler, imzada yalnızca ref/out/in/ref readonlyfarklılık gösteremez.
İmza eşleştirmenin diğer amaçları için (ör. gizlenme veya geçersiz kılma), ref readonlyin değiştirici ile değiştirilebilir, ancak bu durum bildirim sitesinde [§7.6] uyarıyla sonuçlanabilir.
Bu, partial bildirimini uygulamasıyla eşleştirirken ve kesme noktası imzası ile kesişen imzayla eşleştirirken geçerli değildir.
İmzalar ikili uyumlu olmadığından, ref/in ve ref readonly/ref değiştirici çiftleri için geçersiz kılmada bir değişiklik olmadığını, bunların değiştirilemeyeceğini unutmayın.
Tutarlılık için, aynı durum diğer imza eşleştirme amaçları için de geçerlidir (ör. gizleme).
Meta veri kodlama
Hatırlatmak gerekirse,
-
refparametreleri düz byref türleri (IL'deT&) olarak yayılır), -
inparametreleri,refgibidir ve ayrıcaSystem.Runtime.CompilerServices.IsReadOnlyAttributeile ek açıklama yapılır. C# 7.3 ve sonraki sürümlerde[in]ve sanalsamodreq(System.Runtime.InteropServices.InAttribute)ile de gönderilir.
ref readonly parametreleri [in] T&olarak gönderilir ve aşağıdaki öznitelikle ek açıklama eklenir:
namespace System.Runtime.CompilerServices
{
[AttributeUsage(AttributeTargets.Parameter, AllowMultiple = false, Inherited = false)]
public sealed class RequiresLocationAttribute : Attribute
{
}
}
Ayrıca, sanalsa, modreq(System.Runtime.InteropServices.InAttribute) parametreleriyle ikili uyumluluğu sağlamak için in ile birlikte gönderilirler.
in parametrelerin aksine, meta veri boyutunu artırmaktan kaçınmak ve eski derleyici sürümlerinin [IsReadOnly] parametreleri ref readonly parametre olarak yorumlamasını sağlamak için ref readonly parametreleri için ref gösterilmeyeceğini unutmayın (ve bu nedenle ref → ref readonly farklı derleyici sürümleri arasında bile kaynak kıran bir değişiklik olmayacaktır).
RequiresLocationAttribute, ad alanı ile nitelendirilmiş adıyla eşleştirilir ve eğer derlemeye daha önce dahil edilmemişse derleyici tarafından sentezlenir.
Özniteliğin kaynakta belirtilmesi, ParamArrayAttributebenzer şekilde bir parametreye uygulanırsa hata olur.
İşlev işaretçileri
İşlev işaretçilerinde, in parametreler modreq(System.Runtime.InteropServices.InAttribute) ile gönderilir (bkz. işlev işaretçileri teklifi).
ref readonly parametreleri bu modreqolmadan, yerine modopt(System.Runtime.CompilerServices.RequiresLocationAttribute)ile gönderilir.
Eski derleyici sürümleri modopt yoksayar ve bu nedenle ref readonly parametreleri ref parametreler olarak yorumlar (yukarıda açıklandığı gibi ref readonly parametreleri olan normal yöntemler için eski derleyici davranışıyla tutarlıdır) ve modopt tanıyan yeni derleyici sürümleri, ref readonly ve çağrılarısırasında uyarı göndermek üzere parametreleri tanımak için bunu kullanır.
Eski derleyici sürümleriyle tutarlılığı sağlamak için, LangVersion <= 11 etiketini taşıyan yeni derleyici sürümleri, uygun bağımsız değişkenler ref readonly değiştiricisi ile gönderilmediği sürece ref parametrelerinin desteklenmediğine dair hatalar bildirecektir.
İşlev işaretçisi imzalarındaki değiştiricileri ortak API'lerin parçasıysa değiştirmenin ikili bir kesme olduğunu, bu nedenle ref veya inref readonlyolarak değiştirirken ikili bir kesme olacağını unutmayın.
Ancak, normal yöntemlerle tutarlı olarak, işaretçi LangVersion <= 11 çağrı sitesi değiştiricisiyle çağrıldığında in → ref readonly değişikliği yapılırken yalnızca in olan arayanlar için bir kaynak kopması meydana gelir.
Uyumluluk bozucu değişiklikler
Aşırı yükleme çözümlemesindeki ref/in uyumsuzluk gevşemesi, aşağıdaki örnekte gösterildiği gibi bir davranışı bozan değişikliğe sebep oluyor.
class C
{
string M(in int i) => "C";
static void Main()
{
int i = 5;
System.Console.Write(new C().M(ref i));
}
}
static class E
{
public static string M(this C c, ref int i) => "E";
}
C# 11'de çağrı E.M'e bağlanır, bu nedenle "E" yazdırılır.
C# 12'de C.M'ın bağlanmasına bir uyarı ile izin verilir ve çünkü geçerli bir adayımız var, uzantı kapsamları aranmaz, bu nedenle "C" yazdırılır.
Aynı nedenle kaynakta hataya neden olan bir değişiklik de vardır.
Aşağıdaki örnek C# 11'de "1" yazdırır, ancak C# 12'de belirsizlik hatası nedeniyle derlenemez.
var i = 5;
System.Console.Write(C.M(null, ref i));
interface I1 { }
interface I2 { }
static class C
{
public static string M(I1 o, ref int x) => "1";
public static string M(I2 o, in int x) => "2";
}
Yukarıdaki örnekler, yöntem çağrıları için kesintileri göstermektedir, ancak bunlara neden olan aşırı yükleme çözümlemesi değişikliklerinden kaynaklanıyorsa, benzer şekilde yöntem dönüştürmeleri için de tetiklenebilirler.
Alternatif
Parametre bildirimleri
API yazarları, yalnızca lvalue kabul etmek üzere tasarlanmış in parametrelerini özel bir öznitelikle ek açıklama ile işaretleyebilir ve yanlış kullanımları işaretlemek için bir çözümleyici sağlayabilir.
Bu, API yazarlarının ref parametrelerini kullanarak rvalue'ları engellemek için kullanan mevcut API'lerin imzalarını değiştirmesine izin vermez.
Yalnızca bir ref değişkenine erişimi olan API kullanıcılarının ref readonly elde etmek için ek çalışma yapması gerekir.
Bu API'leri ref'dan [RequiresLocation] in'e değiştirmek, kaynakla uyumsuzluk yaratan bir değişiklik olur (ve eğer sanal yöntemler söz konusu ise ikili uyumsuzluk yaratan bir değişikliğe de neden olur).
değiştirici ref readonlyizin vermek yerine, derleyici özel bir özniteliğin ([RequiresLocation]gibi) bir parametreye ne zaman uygulandığını tanıyabilir.
Bu, LDM 2022-04-25'de ele alınmıştı. Bunun çözümleyici değil dil özelliği olduğuna karar vererek, öyle görünmesi gerekir.
Değer türü denetimleri
C++'ın örtük byref parametrelerine benzer şekilde, ref readonly parametrelerine değiştirici olmadan lvalue geçirmesine hiçbir uyarı olmadan izin verilebiliyordu.
Bu, LDM 2022-05-11bölümünde ele alınmıştı ve ref readonly parametreleri için birincil motivasyonun bu parametrelerden başvuruları yakalayan veya döndüren API'ler olduğuna dikkat çekerek, bu nedenle bir tür işaretçinin iyi bir şey olduğunu belirtmektedir.
Rvalue'nin bir ref readonly'a geçirilmesi, uyarı değil, hata olabilir.
Bu, başlangıçta LDM 2022-04-25kabul edildi, ancak daha sonra e-posta tartışmaları bunu gevşetti çünkü mevcut API'leri kullanıcılara zarar vermeden değiştirme yeteneğimizi yitirdik.
in, ref readonly parametreleri için "doğal" çağrı sitesi değiştiricisi olabilir ve ref kullanılması uyarılara neden olabilir.
Bu, tutarlı bir kod stili sağlar ve çağrı alanında başvurunun salt okunur olduğunu (refaksine) belirgin hale getirir.
Başlangıçta LDM 2022-04-25kabul edildi.
Ancak, uyarılar API yazarlarının ref'den ref readonlygeçişine yönelik bir uyuşma noktası olabilir.
Ayrıca, inref readonly + kolaylık özellikleri olarak yeniden tanımlanmıştır, bu nedenle LDM 2022-05-11reddedildi.
LDM incelemesi bekleniyor
C# 12'de aşağıdaki seçeneklerden hiçbiri uygulanmadı. Potansiyel teklifler olarak kalıyor.
Parametre bildirimleri
Değiştiricilerin ters sırasına (readonly refyerineref readonly) izin verilebiliyor.
Bu, readonly ref dönüşlerinin ve alanlarının davranışıyla (ters sıralamaya izin verilmez veya sırasıyla farklı bir şey anlamına gelir) tutarsız olur ve gelecekte uygulanırsa salt okunur parametrelerle çakışmaya neden olabilir.
Varsayılan parametre değerleri, ref readonly parametreleri için bir hata olabilir.
Değer türü denetimleri
ref readonly parametrelerine rvalue geçirildiğinde veya çağrı sitesi ek açıklamaları ile parametre değiştiricileri uyuşmadığında uyarılar yerine hatalar oluşabilir.
Benzer şekilde, modreq parametrelerin ikili düzeydeki ref readonly parametrelerden ayrı olduğundan emin olmak için öznitelik yerine özel in kullanılabilir.
Bu, daha güçlü garantiler sağlar, bu nedenle yeni API'ler için iyi olur, ancak çalışma zamanı esnasında kesinti yaratacak değişiklik yapamayan mevcut API'lerde benimsemeyi engeller.
Değer türü denetimleri, ref aracılığıyla salt okunur başvuruların in/ref readonly parametrelerine geçirilmesine izin verecek şekilde gevşetilebilir.
Ref atamaları ve ref döndürmelerinin bugün çalıştığı şekle benzer olacaktır; ayrıca, kaynak ifadedeki ref değiştiricisi aracılığıyla başvuruların salt okunur olarak geçirilmesine de izin verir.
Bununla birlikte, ref genellikle hedefin ref readonlyolarak tanımlandığı yere yakındır; bu, bağımsız değişken ve parametre değiştiricileri genellikle birbirinden çok uzakta olan çağrıların aksine, referansı salt okunur olarak geçtiğimizin açık olduğunu gösterir.
Ayrıca,
Aşırı Yükleme Çözümü
Aşırı yükleme çözümlemesi, geçersiz kılma ve dönüştürme, ref readonly ve in değiştiricilerin değiştirilememesine izin verebilir.
Mevcut in parametreleri için aşırı yükleme çözümlemesindeki değişiklik LangVersion'a bakılmaksızın koşulsuz olarak alınabilir, ancak bu, mevcut işlevsellikte bozulmaya neden olan bir değişiklik olacaktır.
ref readonly alıcıyla bir uzantı yöntemini çağırmak, çağrı sitesi değiştiricisi olmayan uzantı dışı çağrılarda olduğu gibi "Bağımsız değişken 1 ref veya in anahtar sözcükle geçirilmelidir" uyarısına neden olabilir (kullanıcı, uzantı yöntemi çağırmasını statik yöntem çağrısına dönüştürerek bu uyarıyı düzeltebilir).
Özel koleksiyon başlatıcısı veya ref readonly parametresiyle ilişkilendirilmiş dize işleyicisi kullanılırken aynı uyarı bildirilebilir, ancak kullanıcı bu sorunu gideremedi.
ref readonly aşırı yüklemeleri, bir çağrı sitesi değiştiricisi olmadığında veya bir belirsizlik hatası olduğunda değere göre aşırı yüklemeler yerine tercih edilebilir.
Yöntem dönüşümleri
Hedef yöntemin ref parametresinin temsilcinin in ve ref readonly parametresiyle eşleşmesine izin verebiliriz.
Bu, API yazarlarının, normal yöntem imzaları için izin verilenlerle tutarlı bir şekilde, örneğin temsilci imzalarında ref'ı in olarak değiştirmesine ve kullanıcılarını bozmadan bu değişikliği yapmasına olanak tanır.
Ancak, yalnızca bir uyarıyla aşağıdaki readonly garantilerinin ihlaline de neden olur:
class Program
{
static readonly int f = 123;
static void Main()
{
var d = (in int x) => { };
d = (ref int x) => { x = 42; }; // warning: mismatch between `ref` and `in`
d(f); // changes value of `f` even though it is `readonly`!
System.Console.WriteLine(f); // prints 42
}
}
İşlev işaretçisi dönüştürmeleri ref readonly/ref/in uyuşmazlığı konusunda uyarabilir, ancak bunu LangVersion'da kontrol altına almak isteseydik, tür dönüştürmelerinin bugün derlemeye erişmesi gerekmediğinden bu durum önemli bir uygulama yatırımı gerektirirdi.
Ayrıca, uyuşmazlık şu anda bir hata olarak görülse de, kullanıcıların istedikleri takdirde bu uyuşmazlıklara izin vermek için kolayca bir tür dönüşüm eklemeleri mümkündür.
Metadata kodlama
RequiresLocationAttribute ve In özniteliklerine benzer şekilde kaynaktaki Out belirtilmesine izin verilebiliyor.
Alternatif olarak, IsReadOnly özniteliğine benzer şekilde yalnızca parametrelerden farklı bağlamlarda uygulandığında bir hata olabilir; daha fazla tasarım alanı korumak için.
İşlev işaretçisi ref readonly parametreleri farklı modopt/modreq bileşimleriyle yayılabilir (bu tablodaki "kaynak sonunun" LangVersion <= 11olan arayanlar için anlamına geldiğini unutmayın):
| Değiştiriciler | Derlemeler arasında fark edilebilir | Eski derleyiciler bunları şöyle görür: |
ref → ref readonly |
in → ref readonly |
|---|---|---|---|---|
modreq(In) modopt(RequiresLocation) |
evet | in |
ikili, kaynak sonu | ikili kesme |
modreq(In) |
Hayır | in |
ikili, kaynak sonu | Tamam |
modreq(RequiresLocation) |
evet | Desteklenmeyen | ikili, kaynak sonu | ikili, kaynak sonu |
modopt(RequiresLocation) |
evet | ref |
ikili kesme | ikili, kaynak sonu |
[RequiresLocation] parametreleri için hem [IsReadOnly] hem de ref readonly öznitelikleri yayabiliriz.
Daha sonra in → ref readonly, eski derleyici sürümleri için bile kırıcı bir değişiklik olmaz, ancak ref → ref readonly, eski derleyici sürümleri için kaynak kırıcı değişiklik olur çünkü eski derleyici sürümleri ref readonly'ü inolarak yorumlar ve ref değiştiricilere izin vermez, yeni derleyici sürümleri ise LangVersion <= 11 tutarlılığı sağlamak amacıyla kaynak kırıcı değişiklik olarak değerlendirir.
LangVersion <= 11 davranışını eski derleyici sürümleri için davranıştan farklı hale getirebiliriz.
Örneğin, bir ref readonly parametresi çağrıldığında (çağrı alanında ref değiştirici kullanılırken bile) bir hata oluşabilir veya herhangi bir hata olmadan her zaman buna izin verilir.
Hataya neden olan değişiklikler
Bu teklif, nadiren karşılaşılması gerektiğinden, LangVersion tarafından sınırlanmış olduğundan ve kullanıcıların uzantı yöntemini açıkça çağırarak bu değişikliği aşabilmesi için davranış değiştiren bir hatayı kabul etmeyi önerir. Bunun yerine, bunu şu şekilde azaltabiliriz:
-
ref/inuyumsuzluğuna izin verme (inhenüz kullanılamadığından yalnızcarefkullanan eski API'ler içiningeçişini engeller), - teklif edilen bu değişiklikle, bir referans türü uyuşmazlığı olduğunda, aşağıda belirtilen üstünlük kurallarına göre daha iyi bir eşleşme bulmak için aşırı yükleme çözümleme kurallarının değiştirilmesi,
- veya alternatif olarak yalnızca
refileinuyuşmazlığı için devam edin, diğerleri için değil (ref readonlyvs.ref/in/değere göre).
- veya alternatif olarak yalnızca
İyilik hüküm sürer
Aşağıdaki örnek şu anda üç Mçağrısı için üç belirsizlik hatasına neden olur.
Belirsizlikleri çözmek için yeni iyilik kuralları ekleyebiliriz.
Bu, daha önce açıklanan kaynak kodunu bozan değişikliği de çözer.
Bunun bir yolu, 221'ı örnek olarak yazdırmaktır. Burada, ref readonly parametresi in bağımsız değişkeniyle eşleştirilir çünkü in parametresi için izin verilirken, parametrenin değiştirici olmadan çağrılması bir uyarıya neden olur.
interface I1 { }
interface I2 { }
class C
{
static string M(I1 o, in int i) => "1";
static string M(I2 o, ref readonly int i) => "2";
static void Main()
{
int i = 5;
System.Console.Write(M(null, ref i));
System.Console.Write(M(null, in i));
System.Console.Write(M(null, i));
}
}
Yeni iyileştirme kuralları, farklı bir bağımsız değişken değiştirici kullanılarak daha iyi hale getirilebilecek bir bağımsız değişkenle verilen parametreyi daha kötü olarak işaretleyebilir.
Başka bir deyişle, kullanıcı her zaman ilgili bağımsız değişken değiştiricisini değiştirerek daha kötü bir parametreyi daha iyi bir parametreye dönüştürebilmelidir.
Örneğin, bir bağımsız değişken intarafından geçirildiğinde, kullanıcı ref readonly parametresini seçmek için bağımsız değişkeni değere göre geçirebildiğinden in parametresi yerine bir in parametresi tercih edilir.
Bu kural, bugün geçerli olan değere göre/in tercih kuralının bir uzantısıdır (bu son aşırı yükleme çözümleme kuralıdır ve parametresi daha iyiyse ve hiçbiri başka bir aşırı yüklemenin ilgili parametresinden daha kötü değilse tüm aşırı yükleme daha iyidir).
| tartışma | daha iyi parametre | kötü parametre |
|---|---|---|
ref/in |
ref readonly |
in |
ref |
ref |
ref readonly/in |
| değere göre | değere göre/in |
ref readonly |
in |
in |
ref |
Yöntem dönüştürmelerini benzer şekilde işlememiz gerekir.
Aşağıdaki örnek şu anda iki temsilci ataması için iki belirsizlik hatasına neden olur.
Yeni iyileştirme kuralları, refness değiştiricisi hedef temsilci parametresinin refness değiştiricisi ile eşleşen bir yöntem parametresini, uyuşmayan bir parametreye tercih edebilir.
Bu nedenle, aşağıdaki örnek 12yazacaktır.
class C
{
void M(I1 o, ref readonly int x) => System.Console.Write("1");
void M(I2 o, ref int x) => System.Console.Write("2");
void Run()
{
D1 m1 = this.M;
D2 m2 = this.M; // currently ambiguous
var i = 5;
m1(null, in i);
m2(null, ref i);
}
static void Main() => new C().Run();
}
interface I1 { }
interface I2 { }
class X : I1, I2 { }
delegate void D1(X s, ref readonly int x);
delegate void D2(X s, ref int x);
Tasarım toplantıları
- LDM 2022-04-25: özellik kabul edildi
- LDM 2022-05-09: tartışma üç bölüme ayrılmış
-
LDM 2022-05-11: izin verilen
refveref readonlyparametreleri için çağrı noktası ek açıklaması yok
C# feature specifications