Salt okunur başvurularReadonly references
- [x] önerilir[x] Proposed
- [x] prototipi[x] Prototype
- [x] uygulama: başlatıldı[x] Implementation: Started
- [] Belirtimi: başlatılmadı[ ] Specification: Not Started
ÖzetSummary
"Salt okunur başvurular" özelliği aslında değişkenleri başvuruya göre geçirme ve değişiklikler için verileri açığa çıkarmadan faydalanma verimliliğini kullanan bir özellik grubudur:The "readonly references" feature is actually a group of features that leverage the efficiency of passing variables by reference, but without exposing the data to modifications:
in
parametrelerein
parametersref readonly
döndürdüğüref readonly
returnsreadonly
yapılarreadonly
structsref
/in
Uzantı yöntemleriref
/in
extension methodsref readonly
ayarlanmalıdırref readonly
localsref
Koşullu ifadelerref
conditional expressions
Bağımsız değişkenleri ReadOnly başvuruları olarak geçirme.Passing arguments as readonly references.
Bu konuya, https://github.com/dotnet/roslyn/issues/115 çok sayıda ayrıntıya geçmeden salt okunur parametreleri özel durum olarak dokunan mevcut bir teklif vardır.There is an existing proposal that touches this topic https://github.com/dotnet/roslyn/issues/115 as a special case of readonly parameters without going into many details. Burada yalnızca kendi fikrinin çok yeni olmayacağını bildirmek istiyorum.Here I just want to acknowledge that the idea by itself is not very new.
MotivasyonMotivation
Bu özellik C# ' den önce, hiçbir değişiklik yapmadan salt okunur amaçlar için yapı değişkenlerini metot çağrılarına geçirmeye yönelik etkili bir yola sahip değildir.Prior to this feature C# did not have an efficient way of expressing a desire to pass struct variables into method calls for readonly purposes with no intention of modifying. Normal değere sahip bağımsız değişken geçirme, gereksiz maliyetler ekleyen kopyalamayı gerektirir.Regular by-value argument passing implies copying, which adds unnecessary costs. Bu, kullanıcıların-ref bağımsız değişkenini kullanmasını ve verilerin aranan tarafından atlanması gerektiğini belirtmek için açıklamaları/belgeleri geçen ve kullanıcılara yönlendiren bir belge kullanır.That drives users to use by-ref argument passing and rely on comments/documentation to indicate that the data is not supposed to be mutated by the callee. Birçok nedenden dolayı iyi bir çözüm değildir.It is not a good solution for many reasons.
Örnek olarak, performans konuları nedeniyle, XNA gibi grafik kitaplıklarında çok sayıda vektör/matris matematik işleçleri başvuru işlenenleri olarak bilinir.The examples are numerous - vector/matrix math operators in graphics libraries like XNA are known to have ref operands purely because of performance considerations. Roslyn derleyicisinde, ayırmaların önüne geçmek için yapılar kullanan ve sonra maliyetleri kopyalamayı önlemek için bunları başvuruya göre ileten kod vardır.There is code in Roslyn compiler itself that uses structs to avoid allocations and then passes them by reference to avoid copying costs.
Çözüm ( in
Parametreler)Solution (in
parameters)
Parametrelere benzer şekilde out
, in
Parametreler, çağrılan ek garantilere göre yönetilen başvurular olarak geçirilir.Similarly to the out
parameters, in
parameters are passed as managed references with additional guarantees from the callee.
out
Diğer herhangi bir kullanılmadan önce çağrılan tarafından atanması gereken parametrelerin aksine, in
Parametreler hiçbir şekilde çağrılanın tarafından atanamaz.Unlike out
parameters which must be assigned by the callee before any other use, in
parameters cannot be assigned by the callee at all.
Sonuç olarak, bir sonuç olarak in
, çağrılan bağımsız değişken geçirilen bağımsız değişkenler, çağıran tarafından birbirini tehlikeye atma ile ortaya çıkarmaz.As a result in
parameters allow for effectiveness of indirect argument passing without exposing arguments to mutations by the callee.
in
Parametreleri bildirmeDeclaring in
parameters
in
parametreler in
, anahtar sözcüğü parametre imzasında bir değiştirici olarak kullanılarak belirtilir.in
parameters are declared by using in
keyword as a modifier in the parameter signature.
Tüm amaçlar için in
parametresi bir değişken olarak değerlendirilir readonly
.For all purposes the in
parameter is treated as a readonly
variable. Yöntemi içindeki parametrelerin kullanımı ile ilgili kısıtlamaların çoğu in
readonly
alanlarla aynıdır.Most of the restrictions on the use of in
parameters inside the method are the same as with readonly
fields.
Gerçekten bir
in
parametre bir alanı temsil edebilirreadonly
.Indeed anin
parameter may represent areadonly
field. Kısıtlamaların benzerliği bir rastlantı değildir.Similarity of restrictions is not a coincidence.
Örneğin in
, bir yapı türüne sahip bir parametrenin alan alanları, her yinelemeli olarak değişken olarak sınıflandırıldı readonly
.For example fields of an in
parameter which has a struct type are all recursively classified as readonly
variables .
static Vector3 Add (in Vector3 v1, in Vector3 v2)
{
// not OK!!
v1 = default(Vector3);
// not OK!!
v1.X = 0;
// not OK!!
foo(ref v1.X);
// OK
return new Vector3(v1.X + v2.X, v1.Y + v2.Y, v1.Z + v2.Z);
}
in
Parametreler, normal ByVal parametrelerine izin verildiğinde her yerde kullanılabilir.in
parameters are allowed anywhere where ordinary byval parameters are allowed. Bu, Dizin oluşturucular, işleçler (dönüşümler dahil), temsilciler, Lambdalar, yerel işlevler içerir.This includes indexers, operators (including conversions), delegates, lambdas, local functions.
(in int x) => x // lambda expression TValue this[in TKey index]; // indexer public static Vector3 operator +(in Vector3 x, in Vector3 y) => ... // operator
in
ileout
birleştirilmeyecek hiçbir şeyle veya ile birlikte kullanılamazout
.in
is not allowed in combination without
or with anything thatout
does not combine with.Farklılıklara aşırı yükleme yapılmasına izin verilmez
ref
/out
/in
.It is not permitted to overload onref
/out
/in
differences.Normal ByVal ve farklılıklara aşırı yükleme yapılmasına izin verilir
in
.It is permitted to overload on ordinary byval andin
differences.OHI (aşırı yükleme, gizleme, uygulama) amacıyla,
in
bir parametreye benzer şekilde davranırout
.For the purpose of OHI (Overloading, Hiding, Implementing),in
behaves similarly to anout
parameter. Aynı kuralların hepsi geçerlidir.All the same rules apply. Örneğin, geçersiz kılma yöntemininin
parametreleriin
bir kimlik dönüştürülebilir türün parametreleriyle eşleşmesi gerekecektir.For example the overriding method will have to matchin
parameters within
parameters of an identity-convertible type.Temsilci/Lambda/Yöntem grubu dönüştürmelerinde,
in
bir parametreye benzer şekilde davranırout
.For the purpose of delegate/lambda/method group conversions,in
behaves similarly to anout
parameter. Lambdalar ve geçerli yöntem grubu dönüştürme adaylarıin
,in
kimlik dönüştürülebilir bir tür parametreleriyle hedef temsilcinin parametrelerini eşleştirmek zorunda kalacak.Lambdas and applicable method group conversion candidates will have to matchin
parameters of the target delegate within
parameters of an identity-convertible type.Genel varyans amacına yönelik
in
Parametreler, değişken olmayan bir değişkendir.For the purpose of generic variance,in
parameters are nonvariant.
NOTE:
in
başvuru veya temel türler içeren parametrelerde ilgili bir uyarı yok.NOTE: There are no warnings onin
parameters that have reference or primitives types. Genel olarak daha az olabilir, ancak bazı durumlarda kullanıcının temel temelleri farklı şekilde geçirmek gerekirin
.It may be pointless in general, but in some cases user must/want to pass primitives asin
. Örnekler-olduğu gibi bir genel yöntemi geçersiz kılmaMethod(in T param)
T
int
veya şunun gibi YöntemlerVolatile.Read(in int location)
Examples - overriding a generic method likeMethod(in T param)
whenT
was substituted to beint
, or when having methods likeVolatile.Read(in int location)
Parametrelerin verimsiz kullanımı konusunda uyaran bir çözümleyici Conceivable
in
, ancak bu tür analizler için kurallar bir dil belirtiminin parçası olmak için çok belirsiz olacaktır.It is conceivable to have an analyzer that warns in cases of inefficient use ofin
parameters, but the rules for such analysis would be too fuzzy to be a part of a language specification.
' In in
çağrı sitelerinde kullanımı.Use of in
at call sites. ( in
bağımsız değişkenler)(in
arguments)
Bağımsız değişkenleri parametrelere geçirmek için iki yol vardır in
.There are two ways to pass arguments to in
parameters.
in
bağımsız değişkenler in
parametrelerle eşleşiyor:in
arguments can match in
parameters:
Çağrı sitesinde değiştirici içeren bir bağımsız değişken in
parametrelerle eşleştirebilir in
.An argument with an in
modifier at the call site can match in
parameters.
int x = 1;
void M1<T>(in T x)
{
// . . .
}
var x = M1(in x); // in argument to a method
class D
{
public string this[in Guid index];
}
D dictionary = . . . ;
var y = dictionary[in Guid.Empty]; // in argument to an indexer
in
bağımsız değişken okunabilir bir lvalue (*) olmalıdır.in
argument must be a readable LValue(*). Örnek:M1(in 42)
geçersizExample:M1(in 42)
is invalid
(*) Lvalue/rvalue kavramı diller arasında farklılık gösterir.(*) The notion of LValue/RValue vary between languages.
Burada, LValue tarafından doğrudan başvurulabilen bir konumu temsil eden bir ifade geliyor.Here, by LValue I mean an expression that represent a location that can be referred to directly. Ve RValue, kendi kendine kalıcı olmayan geçici bir sonuç veren bir ifade anlamına gelir.And RValue means an expression that yields a temporary result which does not persist on its own.
Özellikle
readonly
alanları,in
parametreleri veya diğer resmireadonly
değişkenleriin
bağımsız değişken olarak geçirmek için geçerlidir.In particular it is valid to passreadonly
fields,in
parameters or other formallyreadonly
variables asin
arguments. Örnek:dictionary[in Guid.Empty]
geçerlidir.Example:dictionary[in Guid.Empty]
is legal.Guid.Empty
statik salt okunur bir alandır.Guid.Empty
is a static readonly field.in
bağımsız değişken, parametrenin türüne dönüştürülebilir olmalıdır.in
argument must have type identity-convertible to the type of the parameter. Örnek:M1<object>(in Guid.Empty)
geçersiz.Example:M1<object>(in Guid.Empty)
is invalid.Guid.Empty
kimlik-dönüştürülebilir değilobject
Guid.Empty
is not identity-convertible toobject
Yukarıdaki kurallara ilişkin mosyon, bağımsız in
değişkenlerin bağımsız değişken değişkeninin diğer adını garanti eder.The motivation for the above rules is that in
arguments guarantee aliasing of the argument variable. Aranan her zaman bağımsız değişkenle temsil edilen konuma bir doğrudan başvuru alır.The callee always receives a direct reference to the same location as represented by the argument.
in
bağımsız değişkenlerin yığınawait
olarak, aynı çağrının işlenenleri olarak kullanılan ifadeler nedeniyle yığın olarak bir arada olması gerektiğinde, bu davranış ileout
ve bağımsız değişkenlerle aynıdır. değişken, zaman uyumlu olarakref
saydam bir şekilde şeffaf bir şekilde çıkarılamıyor, bir hata bildirilir.in rare situations whenin
arguments must be stack-spilled due toawait
expressions used as operands of the same call, the behavior is the same as without
andref
arguments - if the variable cannot be spilled in referentially-transparent manner, an error is reported.
Örnekler:Examples:
M1(in staticField, await SomethingAsync())
geçerli.M1(in staticField, await SomethingAsync())
is valid.staticField
, observable yan etkileri olmadan birden çok kez erişilebilen statik bir alandır.staticField
is a static field which can be accessed more than once without observable side effects. Bu nedenle, yan etkileri ve diğer ad gereksinimlerinin sırası belirtilebilir.Therefore both the order of side effects and aliasing requirements can be provided.M1(in RefReturningMethod(), await SomethingAsync())
bir hata üretir.M1(in RefReturningMethod(), await SomethingAsync())
will produce an error.RefReturningMethod()
birref
döndürme yöntemidir.RefReturningMethod()
is aref
returning method. Bir yöntem çağrısında observable yan etkileri olabilir, bu nedenle işlenenden önce değerlendirilmelidirSomethingAsync()
.A method call may have observable side effects, therefore it must be evaluated before theSomethingAsync()
operand. Ancak, çağrının sonucuawait
doğrudan başvuru gereksinimini olanaksız hale getirecek olan askıya alma noktası genelinde korunmayan bir başvurudur.However the result of the invocation is a reference that cannot be preserved across theawait
suspension point which make the direct reference requirement impossible.
Not: yığın atımı hatası, uygulamaya özgü sınırlamalar olarak kabul edilir.NOTE: the stack spilling errors are considered to be implementation-specific limitations. Bu nedenle, aşırı yükleme çözünürlüğü veya lambda çıkarımı üzerinde hiçbir etkisi yoktur.Therefore they do not have effect on overload resolution or lambda inference.
Sıradan ByVal bağımsız değişkenleri in
parametrelerle eşleşiyor:Ordinary byval arguments can match in
parameters:
Değiştiriciler olmadan normal bağımsız değişkenler in
parametrelerle eşleşmeyebilir.Regular arguments without modifiers can match in
parameters. Bu tür durumlarda bağımsız değişkenler, sıradan bir ByVal bağımsız değişkenleri ile aynı gevşek kısıtlamalara sahiptir.In such case the arguments have the same relaxed constraints as an ordinary byval arguments would have.
Bu senaryoya ilişkin işlem, in
API 'lerdeki parametrelerin, bağımsız değişkenler doğrudan başvuru-EX olarak geçirilmezse Kullanıcı için nedeniyle ile sonuçlanmasına neden olabilir: değişmez değerler, hesaplanan veya await
Ed sonuçlar veya daha belirli türlere sahip olan bağımsız değişkenler.The motivation for this scenario is that in
parameters in APIs may result in inconveniences for the user when arguments cannot be passed as a direct reference - ex: literals, computed or await
-ed results or arguments that happen to have more specific types.
Tüm bu durumlarda, bağımsız değişken değerini uygun bir yerel türde depolamanın ve yerel olarak bir bağımsız değişken olarak geçirerek oluşan basit bir çözüm vardır in
.All these cases have a trivial solution of storing the argument value in a temporary local of appropriate type and passing that local as an in
argument.
Bu tür ortak kod derleyicisi gereksinimini azaltmak için, in
arama sitesinde değiştirici yoksa, gerekirse aynı dönüşümü gerçekleştirebilir.To reduce the need for such boilerplate code compiler can perform the same transformation, if needed, when in
modifier is not present at the call site.
Bunlara ek olarak, işleçler veya genişletme yöntemlerinin çağrılması gibi bazı durumlarda, hiç bir in
şekilde belirtmenin sözdizimsel bir yolu yoktur in
.In addition, in some cases, such as invocation of operators, or in
extension methods, there is no syntactical way to specify in
at all. Tek başına, parametreleri eşleştiklerinde sıradan ByVal bağımsız değişkenlerinin davranışının belirtilmesini gerektirir in
.That alone requires specifying the behavior of ordinary byval arguments when they match in
parameters.
Özellikle:In particular:
- RValues geçişi için geçerlidir.it is valid to pass RValues. Bu tür bir durumda geçici bir başvuru geçirilir.A reference to a temporary is passed in such case. Örnek:Example:
Print("hello"); // not an error.
void Print<T>(in T x)
{
//. . .
}
- örtük Dönüştürmelere izin verilir.implicit conversions are allowed.
Bu aslında RValue geçirme özel bir durumdurThis is actually a special case of passing an RValue
Bu tür bir durumda, geçici olarak bir dönüştürülmüş değer tutan bir başvuru geçirilir.A reference to a temporary holding converted value is passed in such case. Örnek:Example:
Print<int>(Short.MaxValue) // not an error.
- bir
in
Genişletme yönteminin alıcısında (ref
uzantı yöntemlerinin aksine), rvalues veya örtük Bu bağımsız değişken dönüştürmelerine izin verilir.in a case of a receiver of anin
extension method (as opposed toref
extension methods), RValues or implicit this-argument-conversions are allowed. Bu tür bir durumda, geçici olarak bir dönüştürülmüş değer tutan bir başvuru geçirilir.A reference to a temporary holding converted value is passed in such case. Örnek:Example:
public static IEnumerable<T> Concat<T>(in this (IEnumerable<T>, IEnumerable<T>) arg) => . . .;
("aa", "bb").Concat<char>() // not an error.
Uzantı yöntemleri hakkında daha fazla bilgi ref
/ in
Bu belgede daha fazla sunulmaktadır.More information on ref
/in
extension methods is provided further in this document.
- işlenenler nedeniyle bağımsız değişken atımı
await
, gerekirse "değere göre" taşarakargument spilling due toawait
operands could spill "by-value", if necessary. Bağımsız değişkene doğrudan bir başvuru sağlamak,await
bağımsız değişkenin değerinin bir kopyasının birleştirilmesi nedeniyle mümkün olmadığından, bunun yerineIn scenarios where providing a direct reference to the argument is not possible due to interveningawait
a copy of the argument's value is spilled instead.
Örnek:Example:
M1(RefReturningMethod(), await SomethingAsync()) // not an error.
Yan etkili bir çağrının sonucu, askıya alma genelinde korunmayan bir başvurudur await
, bunun yerine gerçek değeri içeren geçici bir olay korunur (normal bir ByVal parametre durumunda olduğu gibi).Since the result of a side-effecting invocation is a reference that cannot be preserved across await
suspension, a temporary containing the actual value will be preserved instead (as it would in an ordinary byval parameter case).
Atlanan isteğe bağlı bağımsız değişkenlerOmitted optional arguments
in
Parametrenin varsayılan bir değer belirtmesi için izin verilir.It is permitted for an in
parameter to specify a default value. Bu, karşılık gelen bağımsız değişkeni isteğe bağlı hale getirir.That makes the corresponding argument optional.
Çağrı sitesinde isteğe bağlı bağımsız değişkeni atlama, varsayılan değeri geçici olarak geçirme ile sonuçlanır.Omitting optional argument at the call site results in passing the default value via a temporary.
Print("hello"); // not an error, same as
Print("hello", c: Color.Black);
void Print(string s, in Color c = Color.Black)
{
// . . .
}
Genel olarak diğer ad davranışıAliasing behavior in general
Tıpkı ref
ve out
değişkenleri gibi değişkenler, in
var olan konumların başvuruları/diğer adları.Just like ref
and out
variables, in
variables are references/aliases to existing locations.
Çağrılan tarafından bunlara yazma izni verilmediği sürece bir in
parametreyi okumak diğer değerlendirmelere yan bir etkisi olarak farklı değerleri gözlemleyebilirsiniz.While callee is not allowed to write into them, reading an in
parameter can observe different values as a side effect of other evaluations.
Örnek:Example:
static Vector3 v = Vector3.UnitY;
static void Main()
{
Test(v);
}
static void Test(in Vector3 v1)
{
Debug.Assert(v1 == Vector3.UnitY);
// changes v1 deterministically (no races required)
ChangeV();
Debug.Assert(v1 == Vector3.UnitX);
}
static void ChangeV()
{
v = Vector3.UnitX;
}
in
yerel değişkenlerin parametreleri ve yakalanması.in
parameters and capturing of local variables.
Lambda/zaman uyumsuz yakalama parametrelerinin amacı, in
ve parametreleriyle aynı şekilde davranır out
ref
.For the purpose of lambda/async capturing in
parameters behave the same as out
and ref
parameters.
in
Parametreler bir kapanışda yakalanamazin
parameters cannot be captured in a closurein
Yineleyici metotlarda parametrelere izin verilmiyorin
parameters are not allowed in iterator methodsin
zaman uyumsuz yöntemlerde parametrelere izin verilmezin
parameters are not allowed in async methods
Geçici değişkenler.Temporary variables.
Parametre geçirmenin bazı kullanımları, in
geçici bir yerel değişkenin dolaylı kullanımını gerektirebilir:Some uses of in
parameter passing may require indirect use of a temporary local variable:
in
bağımsız değişkenler her zaman, Call-site kullandığında doğrudan diğer adlar olarak geçirilirin
.in
arguments are always passed as direct aliases when call-site usesin
. Geçici, böyle bir durumda hiçbir şekilde kullanılmaz.Temporary is never used in such case.in
çağrı sitesi kullanmıyorsa bağımsız değişkenlerin doğrudan takma adlar olması gerekmezin
.in
arguments are not required to be direct aliases when call-site does not usein
. Bağımsız değişken bir LValue olmadığında geçici bir şekilde kullanılabilir.When argument is not an LValue, a temporary may be used.in
parametrenin varsayılan değeri olabilir.in
parameter may have default value. Çağrı sitesinde karşılık gelen bağımsız değişken atlandığında, varsayılan değer geçici olarak geçirilir.When corresponding argument is omitted at the call site, the default value are passed via a temporary.in
bağımsız değişkenler, kimliği korumayan bulunanlar da dahil olmak üzere örtük Dönüştürmelere sahip olabilir.in
arguments may have implicit conversions, including those that do not preserve identity. Geçici olarak bu durumlarda kullanılır.A temporary is used in those cases.- sıradan yapı çağrılarının alıcıları yazılabilir LValues (mevcut durum!) olamaz.receivers of ordinary struct calls may not be writeable LValues (existing case!). Geçici olarak bu durumlarda kullanılır.A temporary is used in those cases.
Geçiciler bağımsız değişkeninin yaşam süresi, Call-site ' ın en yakın çevreleme kapsamıyla eşleşir.The life time of the argument temporaries matches the closest encompassing scope of the call-site.
Geçici değişkenlerin biçimsel yaşam süresi, başvuruya göre döndürülen değişkenlerin kaçış analizini içeren senaryolarda anlam açısından önemlidir.The formal life time of temporary variables is semantically significant in scenarios involving escape analysis of variables returned by reference.
Parametrelerin meta veri temsili in
.Metadata representation of in
parameters.
System.Runtime.CompilerServices.IsReadOnlyAttribute
Bir ByRef parametresine uygulandığında, parametre bir parametre olduğu anlamına gelir in
.When System.Runtime.CompilerServices.IsReadOnlyAttribute
is applied to a byref parameter, it means that the parameter is an in
parameter.
Ayrıca, yöntem soyut veya sanal ise, bu parametrelerin (ve yalnızca bu parametrelerin) imzası olmalıdır modreq[System.Runtime.InteropServices.InAttribute]
.In addition, if the method is abstract or virtual, then the signature of such parameters (and only such parameters) must have modreq[System.Runtime.InteropServices.InAttribute]
.
Mosyon: Bu, parametreleri geçersiz kılan/uygulayan bir yöntem olması durumunda olduğundan emin olmak için yapılır in
.Motivation: this is done to ensure that in a case of method overriding/implementing the in
parameters match.
Temsilcilerin içindeki yöntemler için de aynı gereksinimler geçerlidir Invoke
.Same requirements apply to Invoke
methods in delegates.
Mosyon: Bu, mevcut derleyicilerin readonly
temsilcileri oluştururken veya atarken yalnızca yoksaymasını sağlamaktır.Motivation: this is to ensure that existing compilers cannot simply ignore readonly
when creating or assigning delegates.
ReadOnly başvurusuyla döndürülüyor.Returning by readonly reference.
MotivasyonMotivation
Bu alt özellik için mosyon, kabaca, kopyalamanın önlenme nedenlerinden in
, ancak döndürülen tarafta yer alır.The motivation for this sub-feature is roughly symmetrical to the reasons for the in
parameters - avoiding copying, but on the returning side. Bu özellikten önce, bir yöntem veya dizin oluşturucunun iki seçeneği vardır: 1) başvuruya göre geri dönün ve olası mutasyonların veya 2), kopyalama ile sonuçlanan değere göre döndürülür.Prior to this feature, a method or an indexer had two options: 1) return by reference and be exposed to possible mutations or 2) return by value which results in copying.
Çözüm ( ref readonly
döndürür)Solution (ref readonly
returns)
Özelliği, bir üyenin değişkenleri bir başvuruya göre geri almasına izin verir.The feature allows a member to return variables by reference without exposing them to mutations.
ref readonly
Döndürülen üyeleri bildirmeDeclaring ref readonly
returning members
Dönüş imzasında değiştiriciler birleşimi ref readonly
, üyenin salt okunur bir başvuru döndürdüğünü göstermek için kullanılır.A combination of modifiers ref readonly
on the return signature is used to to indicate that the member returns a readonly reference.
Tüm amaçlar için bir ref readonly
üye, readonly
alanlar ve parametrelere benzer bir değişken olarak değerlendirilir readonly
in
.For all purposes a ref readonly
member is treated as a readonly
variable - similar to readonly
fields and in
parameters.
Örneğin ref readonly
, bir yapı türüne sahip olan üyenin alanları özyinelemeli olarak değişken olarak sınıflandırıldı readonly
.For example fields of ref readonly
member which has a struct type are all recursively classified as readonly
variables. -Bunları in
bağımsız değişken olarak ref
veya bağımsız değişken olarak geçirmek için izin verilir out
.- It is permitted to pass them as in
arguments, but not as ref
or out
arguments.
ref readonly Guid Method1()
{
}
Method2(in Method1()); // valid. Can pass as `in` argument.
Method3(ref Method1()); // not valid. Cannot pass as `ref` argument
ref readonly
aynı yerlerde dönüşlerine izin verilirref
.ref readonly
returns are allowed in the same places wereref
returns are allowed. Bu, Dizin oluşturucular, temsilciler, Lambdalar, yerel işlevler içerir.This includes indexers, delegates, lambdas, local functions.Açık/farkları aşırı yüklemeye izin verilmez
ref
/ref readonly
.It is not permitted to overload onref
/ref readonly
/ differences.Normal ByVal üzerinde aşırı yükleme ve
ref readonly
geri dönüş farklılıkları vardır.It is permitted to overload on ordinary byval andref readonly
return differences.OHI (aşırı yükleme, gizleme, uygulama) amaçları için
ref readonly
benzer ancak farklıdırref
.For the purpose of OHI (Overloading, Hiding, Implementing),ref readonly
is similar but distinct fromref
. Örneğin, birini geçersiz kılan bir yöntemref readonly
, kendisi olmalıdırref readonly
ve kimlik dönüştürülebilir tür olmalıdır.For example the a method that overridesref readonly
one, must itself beref readonly
and have identity-convertible type.Temsilci/Lambda/Yöntem grubu dönüştürmelerinde,
ref readonly
benzer ancak farklıdırref
.For the purpose of delegate/lambda/method group conversions,ref readonly
is similar but distinct fromref
. Lambdalar ve geçerli yöntem grubu dönüştürme adayları,ref readonly
ref readonly
kimlik dönüştürülebilir olan türün dönüşü ile hedef temsilcinin dönmesini eşleşmelidir.Lambdas and applicable method group conversion candidates have to matchref readonly
return of the target delegate withref readonly
return of the type that is identity-convertible.Genel varyans amacına uygun olmayan
ref readonly
dönüşlerdir.For the purpose of generic variance,ref readonly
returns are nonvariant.
NOTE:
ref readonly
başvuru ya da ilkel türler içeren dönüşlerde uyarı yok.NOTE: There are no warnings onref readonly
returns that have reference or primitives types. Genel olarak daha az olabilir, ancak bazı durumlarda kullanıcının temel temelleri farklı şekilde geçirmek gerekirin
.It may be pointless in general, but in some cases user must/want to pass primitives asin
. Örnekler-olduğu gibi genel bir yöntemi geçersiz kılmaref readonly T Method()
T
int
.Examples - overriding a generic method likeref readonly T Method()
whenT
was substituted to beint
.Dönüşün verimsiz kullanımı durumlarında uyaran bir çözümleyici Conceivable
ref readonly
, ancak bu tür analizler için kurallar bir dil belirtiminin parçası olmak için çok belirsiz olacaktır.It is conceivable to have an analyzer that warns in cases of inefficient use ofref readonly
returns, but the rules for such analysis would be too fuzzy to be a part of a language specification.
Üyelerden dönme ref readonly
Returning from ref readonly
members
Yöntem gövdesinin içinde sözdizimi, normal ref döndürimiyle aynıdır.Inside the method body the syntax is the same as with regular ref returns. , readonly
Kapsayan yönteminden çıkarsedilir.The readonly
will be inferred from the containing method.
Mosyon, return ref readonly <expression>
gereksizdir ve yalnızca readonly
her zaman hatalara neden olacak bölümde uyuşmazlıkların yapılmasına izin verir.The motivation is that return ref readonly <expression>
is unnecessary long and only allows for mismatches on the readonly
part that would always result in errors.
ref
Ancak, bir şeyin kesin diğer ad ile ve değere göre geçirildiği diğer senaryolarla tutarlılık için gereklidir.The ref
is, however, required for consistency with other scenarios where something is passed via strict aliasing vs. by value.
Parametrelerden farklı olarak
in
,ref readonly
bir yerel kopya aracılığıyla hiçbir şekilde geri dönmeme döndürür.Unlike the case within
parameters,ref readonly
returns never return via a local copy. Kopyanın bu tür bir uygulama döndürüldüğünde hemen mevcut olmaya başlayacağından emin olmak, daha az ve tehlikeli olur.Considering that the copy would cease to exist immediately upon returning such practice would be pointless and dangerous. Bu nedenleref readonly
, dönüş her zaman doğrudan referanslardır.Thereforeref readonly
returns are always direct references.
Örnek:Example:
struct ImmutableArray<T>
{
private readonly T[] array;
public ref readonly T ItemRef(int i)
{
// returning a readonly reference to an array element
return ref this.array[i];
}
}
- Bağımsız değişkeninin
return ref
lvalue olması gerekir (var olan kural)An argument ofreturn ref
must be an LValue (existing rule) - Bağımsız değişkeninin
return ref
"dönmesi için güvenli" olması gerekir (var olan kural)An argument ofreturn ref
must be "safe to return" (existing rule) - Üyesinin bir
ref readonly
bağımsız değişkenininreturn ref
yazılabilir olması gerekmez.In aref readonly
member an argument ofreturn ref
is not required to be writeable . Örneğin, bu tür üye başvuru alabilir-salt okunur bir alan veya parametrelerinden birini döndürürin
.For example such member can ref-return a readonly field or one of itsin
parameters.
Kuralları döndürmek için güvenli.Safe to Return rules.
Başvuru kuralları için normal güvenli, salt okunur başvurulara de uygulanır.Normal safe to return rules for references will apply to readonly references as well.
Bir, bir ref readonly
normal ref
yerel/parametre/dönüşten elde edilebilir, ancak başka bir yoldan alınkullanılamayacağını unutmayın.Note that a ref readonly
can be obtained from a regular ref
local/parameter/return, but not the other way around. Aksi takdirde, ref readonly
döndürmenin güvenliği, düzenli dönüşler için aynı şekilde algılanır ref
.Otherwise the safety of ref readonly
returns is inferred the same way as for regular ref
returns.
Bu RValues 'un parametre olarak geçirilebilir in
ve ref readonly
bir daha fazla kurala ihtiyaç duyduğumuz için geri dönülebilecek şekilde düşünüldüğünde , başvuruya göre güvenli dönüşsüz-rvalues.Considering that RValues can be passed as in
parameter and returned as ref readonly
we need one more rule - RValues are not safe-to-return by reference.
Bir RValue bir parametreye bir parametre ile geçirildiğinde
in
ve sonra bir biçiminde geri döndürüldüğünde durumu göz önünde bulundurunref readonly
.Consider the situation when an RValue is passed to anin
parameter via a copy and then returned back in a form of aref readonly
. Çağıran bağlamında, bu tür çağrının sonucu, yerel verilere yönelik bir başvurudur ve bu nedenle bu, döndürülmek üzere güvenli değildir.In the context of the caller the result of such invocation is a reference to local data and as such is unsafe to return. RValues değeri dönmek için güvenli olmadıktan sonra var olan kural#6
Bu durumu zaten işler.Once RValues are not safe to return, the existing rule#6
already handles this case.
Örnek:Example:
ref readonly Vector3 Test1()
{
// can pass an RValue as "in" (via a temp copy)
// but the result is not safe to return
// because the RValue argument was not safe to return by reference
return ref Test2(default(Vector3));
}
ref readonly Vector3 Test2(in Vector3 r)
{
// this is ok, r is returnable
return ref r;
}
Güncelleştirilmiş safe to return
kurallar:Updated safe to return
rules:
- yığındaki değişkenlere başvuruların dönmesi için güvenlidirrefs to variables on the heap are safe to return
- ref/in parametrelerinin döndürülmesi güvenli
in
Parametreler doğal olarak yalnızca ReadOnly olarak döndürülebilir.ref/in parameters are safe to returnin
parameters naturally can only be returned as readonly. - Out parametrelerinin dönmesi güvenlidir (ancak zaten bugün olduğu gibi, kesinlikle atanması gerekir)out parameters are safe to return (but must be definitely assigned, as is already the case today)
- alıcının dönmesi güvenli olduğu sürece örnek struct alanları geri dönmek için güvenlidirinstance struct fields are safe to return as long as the receiver is safe to return
- ' this ', yapı üyelerinden dönmek için güvenli değildir'this' is not safe to return from struct members
- başka bir yöntemden döndürülen ref, bu yönteme biçimsel parametreler olarak geçirilen tüm ReFS/ıse 'nin dönmesi güvenli olduğu durumlarda döndürülür. Alıcının bir struct, Class veya genel bir tür parametresi olarak yazılmış olmasına bakılmaksızın, özellikle alıcı dönmek için güvenli hale gelir.a ref, returned from another method is safe to return if all refs/outs passed to that method as formal parameters were safe to return. Specifically it is irrelevant if receiver is safe to return, regardless whether receiver is a struct, class or typed as a generic type parameter.
- Rvalues, başvuruya göre dönmek için güvenli değildir. Özellikle RValues, parametrelere göre geçiş için güvenlidir.RValues are not safe to return by reference. Specifically RValues are safe to pass as in parameters.
NOTE: ref benzeri türler ve ref atamaları dahil edildiğinde yürütmeye gelen dönüşlerle ilgili ek kurallar vardır.NOTE: There are additional rules regarding safety of returns that come into play when ref-like types and ref-reassignments are involved. Kurallar ve üyeleri için aynı şekilde geçerlidir
ref
ref readonly
ve bu nedenle burada bahsedilmez.The rules equally apply toref
andref readonly
members and therefore are not mentioned here.
Diğer ad davranışı.Aliasing behavior.
ref readonly
Üyeler sıradan üyelerle aynı diğer ad davranışını ref
(ReadOnly olması dışında) sağlar.ref readonly
members provide the same aliasing behavior as ordinary ref
members (except for being readonly).
Bu nedenle, Lambdalar, zaman uyumsuz, yineleyiciler, yığın sıçraıcı vb. için yakalama amacına yöneliktir. aynı kısıtlamalar geçerlidir.Therefore for the purpose of capturing in lambdas, async, iterators, stack spilling etc... the same restrictions apply. Yani.- I.E. gerçek başvuruların yakalanmasının nedeni ve üye değerlendirmesinin yan yana etkili olması nedeniyle bu senaryolara izin verilmez.due to inability to capture the actual references and due to side-effecting nature of member evaluation such scenarios are disallowed.
ref readonly
Dönüş, düzenli bir yazılabilir başvuru olarak kabul edilecek ve normal bir yapı yöntemlerinin alıcısı olduğunda bir kopya oluşturmak için izin verilir ve gereklidirthis
.It is permitted and required to make a copy whenref readonly
return is a receiver of regular struct methods, which takethis
as an ordinary writeable reference. Tarihsel olarak, bu tür bir çağırmaları ReadOnly değişkenine uygulandığı her durumda yerel bir kopya yapılır.Historically in all cases where such invocations are applied to readonly variable a local copy is made.
Meta veri gösterimi.Metadata representation.
System.Runtime.CompilerServices.IsReadOnlyAttribute
Bir ByRef döndüren metodun dönüşe uygulandığında, yöntemin salt okunur bir başvuru döndürdüğü anlamına gelir.When System.Runtime.CompilerServices.IsReadOnlyAttribute
is applied to the return of a byref returning method, it means that the method returns a readonly reference.
Ayrıca, bu yöntemlerin sonuç imzası (ve yalnızca bu yöntemler) olmalıdır modreq[System.Runtime.CompilerServices.IsReadOnlyAttribute]
.In addition, the result signature of such methods (and only those methods) must have modreq[System.Runtime.CompilerServices.IsReadOnlyAttribute]
.
Mosyon: Bu, mevcut derleyicilerin readonly
dönüşlerle yöntemleri çağırırken yalnızca yoksaymasını sağlamaktır ref readonly
Motivation: this is to ensure that existing compilers cannot simply ignore readonly
when invoking methods with ref readonly
returns
ReadOnly yapılarReadonly structs
Kısaca this
Oluşturucu, bir parametre haricinde bir yapının tüm örnek üyelerinin parametresini yapan bir özellik in
.In short - a feature that makes this
parameter of all instance members of a struct, except for constructors, an in
parameter.
MotivasyonMotivation
Derleyici, bir struct örneğindeki herhangi bir yöntem çağrısının örneği değiştireolabileceğini varsaymalıdır.Compiler must assume that any method call on a struct instance may modify the instance. Aslında yazılabilir bir başvuru yönteme parametre olarak geçirilir this
ve bu davranışı tamamen sağlar.Indeed a writeable reference is passed to the method as this
parameter and fully enables this behavior. Değişkenlerde bu tür çağırmaları sağlamak için readonly
, çağırmaları geçici kopyalara uygulanır.To allow such invocations on readonly
variables, the invocations are applied to temp copies. Bu, sezgisel hale gelebilir ve bazen kişilerin performans nedenleriyle iptal etmeye zorlar readonly
.That could be unintuitive and sometimes forces people to abandon readonly
for performance reasons.
Örnek: https://codeblog.jonskeet.uk/2014/07/16/micro-optimization-the-surprising-inefficiency-of-readonly-fields/Example: https://codeblog.jonskeet.uk/2014/07/16/micro-optimization-the-surprising-inefficiency-of-readonly-fields/
Parametreler için destek ekledikten in
ve ref readonly
daha sonra, salt okunur değişkenler daha yaygın hale gelediğinden, savunmaya yönelik kopyalama sorununu döndürmenizden sonraAfter adding support for in
parameters and ref readonly
returns the problem of defensive copying will get worse since readonly variables will become more common.
ÇözümSolution
readonly
Yapı bildirimlerinde değiştiriciye izin verin, bu, this
in
oluşturucular hariç tüm yapı örneği yöntemlerinde parametre olarak değerlendirilmelidir.Allow readonly
modifier on struct declarations which would result in this
being treated as in
parameter on all struct instance methods except for constructors.
static void Test(in Vector3 v1)
{
// no need to make a copy of v1 since Vector3 is a readonly struct
System.Console.WriteLine(v1.ToString());
}
readonly struct Vector3
{
. . .
public override string ToString()
{
// not OK!! `this` is an `in` parameter
foo(ref this.X);
// OK
return $"X: {X}, Y: {Y}, Z: {Z}";
}
}
ReadOnly yapısının üyeleri hakkında kısıtlamalarRestrictions on members of readonly struct
- ReadOnly yapısının örnek alanları salt okunur olmalıdır.Instance fields of a readonly struct must be readonly.
Mosyon: yalnızca harici olarak yazılabilir ancak üyelere eklenebilir.Motivation: can only be written to externally, but not through members. - Salt okunur bir yapının örnek oto özellikleri salt al olmalıdır.Instance autoproperties of a readonly struct must be get-only.
Mosyon: örnek alanlarında kısıtlamanın sonucu.Motivation: consequence of restriction on instance fields. - ReadOnly struct alan benzeri olayları bildiremeyebilir.Readonly struct may not declare field-like events.
Mosyon: örnek alanlarında kısıtlamanın sonucu.Motivation: consequence of restriction on instance fields.
Meta veri gösterimi.Metadata representation.
System.Runtime.CompilerServices.IsReadOnlyAttribute
Değer türüne uygulandığında, türün bir olması anlamına gelir readonly struct
.When System.Runtime.CompilerServices.IsReadOnlyAttribute
is applied to a value type, it means that the type is a readonly struct
.
Özellikle:In particular:
IsReadOnlyAttribute
Türün kimliği önemli değildir.The identity of theIsReadOnlyAttribute
type is unimportant. Aslında, gerekirse kapsayan derlemede derleyici tarafından gömülebilir.In fact it can be embedded by the compiler in the containing assembly if needed.
ref
/in
Uzantı yöntemleriref
/in
extension methods
Aslında mevcut bir teklif ( https://github.com/dotnet/roslyn/issues/165) ve buna karşılık gelen PROTOTIP PR ( https://github.com/dotnet/roslyn/pull/15650) .There is actually an existing proposal (https://github.com/dotnet/roslyn/issues/165) and corresponding prototype PR (https://github.com/dotnet/roslyn/pull/15650).
Yalnızca bu fikrin tamamen yeni olduğunu bildirmek istiyorum.I just want to acknowledge that this idea is not entirely new. Bununla birlikte, bu ref readonly
tür yöntemler hakkında en iyi şeyleri ortadan kaldırdığından ve rvalue alıcılarından ne yapabileceğiniz hakkında daha fazla bilgi için burada da geçerlidir.It is, however, relevant here since ref readonly
elegantly removes the most contentious issue about such methods - what to do with RValue receivers.
Genel fikir, this
tür bir yapı türü olarak bilindiğinde, uzantı yöntemlerinin parametreyi başvuruya göre geçirmesine olanak sağlar.The general idea is allowing extension methods to take the this
parameter by reference, as long as the type is known to be a struct type.
public static void Extension(ref this Guid self)
{
// do something
}
Bu tür uzantı yöntemlerini yazma nedenleri öncelikle şunlardır:The reasons for writing such extension methods are primarily:
- Alıcı büyük bir yapı olduğunda kopyalamayı önleyinAvoid copying when receiver is a large struct
- Yapı birimlerinde uzantı yöntemlerinin değiştirilmesine izin verAllow mutating extension methods on structs
Sınıflarda buna izin vermek istemediğimiz nedenlerThe reasons why we do not want to allow this on classes
- Çok sınırlı bir amaç olabilir.It would be of very limited purpose.
- Yöntem çağrısının,
null
çağrıdan sonra olmak üzere alıcı olmayan bir şekilde dönemeyeceği uzun bir bozar kesernull
.It would break long standing invariant that a method call cannot turn non-null
receiver to becomenull
after invocation.
Aslında,
null
null
ya da veya tarafından açıkça atanmamışsa veya geçirilmediği halde değişken olmayan birref
olmazout
.In fact, currently a non-null
variable cannot becomenull
unless explicitly assigned or passed byref
orout
. Okunabilirliği veya diğer "Bu tür", "Bu bir null" analizinden büyük ölçüde yardımcı olur.That greatly aids readability or other forms of "can this be a null here" analysis. 3. Null koşullu erişimlerin "bir kez değerlendir" semantiğinin uzlanması zor olabilir.It would be hard to reconcile with "evaluate once" semantics of null-conditional accesses. Örnek:obj.stringField?.RefExtension(...)
-stringField
null denetimini anlamlı hale getirmek için bir kopyasını yakalamanız gerekir, ancak sonrathis
refextension içindeki atamalar alana geri yansıtılmaz.Example:obj.stringField?.RefExtension(...)
- need to capture a copy ofstringField
to make the null check meaningful, but then assignments tothis
inside RefExtension would not be reflected back to the field.
Başvuruya göre ilk bağımsız değişkeni alan yapılar üzerinde uzantı yöntemleri bildirme yeteneği uzun süreli bir istek idi.An ability to declare extension methods on structs that take the first argument by reference was a long-standing request. Engellenmeden biri "alıcı LValue değilse ne olur?" idi.One of the blocking consideration was "what happens if receiver is not an LValue?".
- Herhangi bir uzantı yönteminin statik bir yöntem olarak da çağrılacağından, bazı durumlarda belirsizlik çözümlenmenin tek yolu vardır.There is a precedent that any extension method could also be called as a static method (sometimes it is the only way to resolve ambiguity). RValue alıcılarının izin verilmemelidir.It would dictate that RValue receivers should be disallowed.
- Öte yandan, yapı örneği yöntemleri dahil edildiğinde benzer durumlarda bir kopyaya çağrı yapma yöntemi vardır.On the other hand there is a practice of making invocation on a copy in similar situations when struct instance methods are involved.
"Örtük kopyalama" olmasının nedeni, yapı yöntemlerinin büyük çoğunluğunun, bunu belirtemediği sürece yapıyı gerçekten değiştirmeleridir.The reason why the "implicit copying" exists is because the majority of struct methods do not actually modify the struct while not being able to indicate that. Bu nedenle en pratik çözüm, yalnızca bir kopyaya çağrı yapmak için, ancak bu uygulama, çok fazla performans ve hatalara neden olduğu bilinmektedir.Therefore the most practical solution was to just make the invocation on a copy, but this practice is known for harming performance and causing bugs.
Artık parametrelerin kullanılabilirliğiyle in
, bir uzantının amacı işaret etmek mümkündür.Now, with availability of in
parameters, it is possible for an extension to signal the intent. Bu nedenle Conundrum, ref
in
Uzantılar, gerektiğinde örtük kopyalamaya izin verdiğinden yazılabilir alıcılarla çağrılması gerekmeden çözülebilir.Therefore the conundrum can be resolved by requiring ref
extensions to be called with writeable receivers while in
extensions permit implicit copying if necessary.
// this can be called on either RValue or an LValue
public static void Reader(in this Guid self)
{
// do something nonmutating.
WriteLine(self == default(Guid));
}
// this can be called only on an LValue
public static void Mutator(ref this Guid self)
{
// can mutate self
self = new Guid();
}
in
Uzantılar ve genel türler.in
extensions and generics.
ref
Uzantı yöntemlerinin amacı, alıcıyı doğrudan veya üye değiştirici çağırarak çağırmak için kullanılır.The purpose of ref
extension methods is to mutate the receiver directly or by invoking mutating members. Bu nedenle ref this T
uzantılara T
, bir struct olarak kısıtlanan sürece izin verilir.Therefore ref this T
extensions are allowed as long as T
is constrained to be a struct.
Diğer yandan in
Uzantı yöntemleri, örtük kopyalamayı azaltmak için özellikle vardır.On the other hand in
extension methods exist specifically to reduce implicit copying. Ancak, bir parametresinin tüm kullanımı in T
bir arabirim üyesi aracılığıyla yapılmalıdır.However any use of an in T
parameter will have to be done through an interface member. Tüm arabirim üyeleri değişikliğe karşı kabul edildiğinden, bu tür bir kullanım için bir kopya gerekir.Since all interface members are considered mutating, any such use would require a copy. -Kopyalamayı azaltmak yerine, efekt tersi olur.- Instead of reducing copying, the effect would be the opposite. in this T
T
Kısıtlamaların ne olursa olsun genel tür parametresi olduğunda bu nedenle izin verilmez.Therefore in this T
is not allowed when T
is a generic type parameter regardless of constraints.
Geçerli uzantı yöntemleri türleri (Recap):Valid kinds of extension methods (recap):
this
Bir genişletme yönteminde aşağıdaki bildirim formlarına artık izin verilir:The following forms of this
declaration in an extension method are now allowed:
this T arg
-normal ByVal uzantısı.this T arg
- regular byval extension. (mevcut durum)(existing case)
T, başvuru türleri veya tür parametreleri de dahil olmak üzere herhangi bir tür olabilir.T can be any type, including reference types or type parameters. Örnek, çağrıdan sonra aynı değişken olacaktır.Instance will be the same variable after the call. Bu bağımsız değişken dönüştürme türünün örtük dönüştürmelerine izin verir.Allows implicit conversions of this-argument-conversion kind. , RValues üzerinde çağrılabilir.Can be called on RValues.
in this T self
-in
uzantının.in this T self
-in
extension. T gerçek bir yapı türü olmalıdır.T must be an actual struct type. Örnek, çağrıdan sonra aynı değişken olacaktır.Instance will be the same variable after the call. Bu bağımsız değişken dönüştürme türünün örtük dönüştürmelerine izin verir.Allows implicit conversions of this-argument-conversion kind. , RValues üzerinde çağrılabilir (gerekirse geçici bir durum üzerinde çağrılabilir).Can be called on RValues (may be invoked on a temp if needed).ref this T self
-ref
uzantının.ref this T self
-ref
extension. T bir struct türü ya da bir struct olarak kısıtlanmış genel tür parametresi olmalıdır.T must be a struct type or a generic type parameter constrained to be a struct. Örnek, çağırma tarafından yazılmış olabilir.Instance may be written to by the invocation. Yalnızca kimlik dönüştürmelerine izin verir.Allows only identity conversions. Yazılabilir LValue üzerinde çağrılmalıdır.Must be called on writeable LValue. (bir geçici aracılığıyla hiçbir şekilde çağırılmaz).(never invoked via a temp).
Salt okunur başvuru yerelleri.Readonly ref locals.
Amacı.Motivation.
ref readonly
Üyeler tanıtıldıktan sonra, uygun tür yerel ile eşleştirilmeleri gereken kullanımı ortadan kaldırıldı.Once ref readonly
members were introduced, it was clear from the use that they need to be paired with appropriate kind of local. Bir üyenin değerlendirilmesi yan etkileri oluşturabilir veya gözlemlenebilir, bu nedenle sonuç birden çok kez kullanılacaksa, depolanması gerekir.Evaluation of a member may produce or observe side effects, therefore if the result must be used more than once, it needs to be stored. Sıradan ref
Yereller, bir başvuru atanmadığından buraya yardım etmez readonly
.Ordinary ref
locals do not help here since they cannot be assigned a readonly
reference.
Çözümden.Solution.
Yerelleri bildirmek için izin verin ref readonly
.Allow declaring ref readonly
locals. Bu, yazılabilir olmayan yeni bir ref
yereltür türüdür.This is a new kind of ref
locals that is not writeable. Sonuç olarak ref readonly
, Yereller yazma için bu değişkenleri ortaya çıkarmadan ReadOnly değişkenlerine başvuruları kabul edebilir.As a result ref readonly
locals can accept references to readonly variables without exposing these variables to writes.
Yereller bildirme ve kullanma ref readonly
.Declaring and using ref readonly
locals.
Bu tür Yereller sözdizimi, ref readonly
bildirim sitesinde (bu belirli sırada) değiştiriciler kullanır.The syntax of such locals uses ref readonly
modifiers at declaration site (in that specific order). Sıradan Yereller 'e benzer şekilde ref
, ref readonly
Yereller, bildirimde ref-Initialized olmalıdır.Similarly to ordinary ref
locals, ref readonly
locals must be ref-initialized at declaration. Normal ref
Yerellerden farklı olarak, ref readonly
Yereller readonly
in
Parametreler, readonly
alanlar, yöntemler gibi lvalues 'a başvurabilir ref readonly
.Unlike regular ref
locals, ref readonly
locals can refer to readonly
LValues like in
parameters, readonly
fields, ref readonly
methods.
Tüm amaçlar için ref readonly
yerel bir değişken olarak değerlendirilir readonly
.For all purposes a ref readonly
local is treated as a readonly
variable. Kullanım üzerindeki kısıtlamaların çoğu readonly
alanlarla veya in
parametrelerle aynıdır.Most of the restrictions on the use are the same as with readonly
fields or in
parameters.
Örneğin in
, bir yapı türüne sahip bir parametrenin alan alanları, her yinelemeli olarak değişken olarak sınıflandırıldı readonly
.For example fields of an in
parameter which has a struct type are all recursively classified as readonly
variables .
static readonly ref Vector3 M1() => . . .
static readonly ref Vector3 M1_Trace()
{
// OK
ref readonly var r1 = ref M1();
// Not valid. Need an LValue
ref readonly Vector3 r2 = ref default(Vector3);
// Not valid. r1 is readonly.
Mutate(ref r1);
// OK.
Print(in r1);
// OK.
return ref r1;
}
Yereller kullanımıyla ilgili kısıtlamalar ref readonly
Restrictions on use of ref readonly
locals
readonly
ref readonly
Yereller dışında, Yereller sıradan ref
Yereller gibi davranır ve tam olarak aynı kısıtlamalara tabidir.Except for their readonly
nature, ref readonly
locals behave like ordinary ref
locals and are subject to exactly same restrictions.
Örneğin, kapanışlarda yakalama ile ilgili kısıtlamalar, async
Yöntemler veya safe-to-return
analizde aynı şekilde, Yereller için de geçerlidir ref readonly
.For example restrictions related to capturing in closures, declaring in async
methods or the safe-to-return
analysis equally applies to ref readonly
locals.
Üçlü ref
ifadeler.Ternary ref
expressions. (diğer adıyla "şartlı LValues")(aka "Conditional LValues")
MotivasyonMotivation
Ve Yereller 'in kullanımı, bir ref
ref readonly
koşula bağlı olarak bir veya başka bir hedef değişkeni ile bu tür yerelleri bir veya daha fazla yerelden başlatmaya gerekUse of ref
and ref readonly
locals exposed a need to ref-initialize such locals with one or another target variable based on a condition.
Tipik bir geçici çözüm, şunun gibi bir yöntemi tanıtmaktadır:A typical workaround is to introduce a method like:
ref T Choice(bool condition, ref T consequence, ref T alternative)
{
if (condition)
{
return ref consequence;
}
else
{
return ref alternative;
}
}
Choice
Tüm bağımsız değişkenlerin, sezgisel olmayan davranış ve hatalara yönelik olarak önde gelen çağrı sitesinde değerlendirilmesi gerektiğinden, bir Üçlü tam değiştirme değildir.Note that Choice
is not an exact replacement of a ternary since all arguments must be evaluated at the call site, which was leading to unintuitive behavior and bugs.
Aşağıdakiler beklendiği gibi çalışmayacak:The following will not work as expected:
// will crash with NRE because 'arr[0]' will be executed unconditionally
ref var r = ref Choice(arr != null, ref arr[0], ref otherArr[0]);
ÇözümSolution
Bir koşula bağlı olarak LValue bağımsız değişkeninden birine başvuru olarak değerlendirilen, özel tür koşullu ifadeye izin verin.Allow special kind of conditional expression that evaluates to a reference to one of LValue argument based on a condition.
ref
Üçlü ifade kullanma.Using ref
ternary expression.
ref
Koşullu ifade türü için sözdizimi<condition> ? ref <consequence> : ref <alternative>;
The syntax for the ref
flavor of a conditional expression is <condition> ? ref <consequence> : ref <alternative>;
Yalnızca normal koşullu ifade gibi <consequence>
ya da <alternative>
Boolean koşul ifadesinin sonucuna bağlı olarak değerlendirilir.Just like with the ordinary conditional expression only <consequence>
or <alternative>
is evaluated depending on result of the boolean condition expression.
Sıradan koşullu ifadenin aksine, ref
koşullu ifade:Unlike ordinary conditional expression, ref
conditional expression:
- ,
<consequence>
ve<alternative>
değerlerinin lvalues olmasını gerektirir.requires that<consequence>
and<alternative>
are LValues. ref
koşullu ifadenin kendisi bir LValue veref
conditional expression itself is an LValue andref
hem hem de<consequence>
<alternative>
yazılabilir lvalues olduğunda koşullu ifade yazılabilirref
conditional expression is writeable if both<consequence>
and<alternative>
are writeable LValues
Örnekler:Examples:
ref
Üçlü, bir LValue ve başvuruya göre geçirilebilir/atanabilir/döndürülebilir.ref
ternary is an LValue and as such it can be passed/assigned/returned by reference;
// pass by reference
foo(ref (arr != null ? ref arr[0]: ref otherArr[0]));
// return by reference
return ref (arr != null ? ref arr[0]: ref otherArr[0]);
LValue olarak da atanabilir.Being an LValue, it can also be assigned to.
// assign to
(arr != null ? ref arr[0]: ref otherArr[0]) = 1;
// error. readOnlyField is readonly and thus conditional expression is readonly
(arr != null ? ref arr[0]: ref obj.readOnlyField) = 1;
, Bir yöntem çağrısının alıcısı olarak kullanılabilir ve gerekirse kopyalamayı atlayabilirsiniz.Can be used as a receiver of a method call and skip copying if necessary.
// no copies
(arr != null ? ref arr[0]: ref otherArr[0]).StructMethod();
// invoked on a copy.
// The receiver is `readonly` because readOnlyField is readonly.
(arr != null ? ref arr[0]: ref obj.readOnlyField).StructMethod();
// no copies. `ReadonlyStructMethod` is a method on a `readonly` struct
// and can be invoked directly on a readonly receiver
(arr != null ? ref arr[0]: ref obj.readOnlyField).ReadonlyStructMethod();
ref
Üçlü, normal (Ref değil) bağlamda de kullanılabilir.ref
ternary can be used in a regular (not ref) context as well.
// only an example
// a regular ternary could work here just the same
int x = (arr != null ? ref arr[0]: ref otherArr[0]);
BulunmaktadırDrawbacks
Başvurular ve salt okunur başvurular için gelişmiş desteğe karşı iki önemli bağımsız değişken görebiliyorum:I can see two major arguments against enhanced support for references and readonly references:
- Burada çözülen sorunlar çok eski.The problems that are solved here are very old. Özellikle de, var olan koda yardımcı olmadığından, neden daha önce bu dosyaları şimdi çözmektedir?Why suddenly solve them now, especially since it would not help existing code?
Yeni etki alanlarında kullanılan C# ve .net ' i bulduğumuz için bazı sorunlar daha belirgin hale gelir.As we find C# and .Net used in new domains, some problems become more prominent.
Hesaplama fazla kafaları hakkında ortalamaya göre daha kritik olan ortamlara örnek olarak, şunları ListelerimAs examples of environments that are more critical than average about computation overheads, I can list
- hesaplamanın faturalandırılması ve yanıt verebildiği bulut/veri merkezi senaryoları rekabetçi bir avantajdır.cloud/datacenter scenarios where computation is billed for and responsiveness is a competitive advantage.
- Gecikme sürelerinde geçici gerçek zamanlı gereksinimlere sahip Oyunlar/VR/ARGames/VR/AR with soft-realtime requirements on latencies
Bu özellik, bazı yaygın senaryolarda daha fazla gözlerine izin verirken tür-güvenlik gibi mevcut güçlerin hiçbirini etkilemez.This feature does not sacrifice any of the existing strengths such as type-safety, while allowing to lower overheads in some common scenarios.
- Çağrılan kuralların, sözleşmelerde ne zaman kabul eteceğimizi makul ölçüde garanti edebilir
readonly
mi?Can we reasonably guarantee that the callee will play by the rules when it opts intoreadonly
contracts?
Kullanırken benzer bir güveniz var out
.We have similar trust when using out
. Yanlış uygulanması out
belirtilmeyen davranışa neden olabilir, ancak gerçekte nadiren meydana gelir.Incorrect implementation of out
can cause unspecified behavior, but in reality it rarely happens.
Resmi doğrulama kurallarının tanıdık getirilmesi, ref readonly
güven sorununu daha da hafifletmeye devam edecektir.Making the formal verification rules familiar with ref readonly
would further mitigate the trust issue.
AlternatiflerAlternatives
Asıl rekabet tasarımı gerçekten "hiçbir şey yapmaz".The main competing design is really "do nothing".
Çözümlenmemiş sorularUnresolved questions
Tasarım toplantılarıDesign meetings
https://github.com/dotnet/csharplang/blob/master/meetings/2017/LDM-2017-02-22.md https://github.com/dotnet/csharplang/blob/master/meetings/2017/LDM-2017-03-01.md https://github.com/dotnet/csharplang/blob/master/meetings/2017/LDM-2017-08-28.md https://github.com/dotnet/csharplang/blob/master/meetings/2017/LDM-2017-09-25.md https://github.com/dotnet/csharplang/blob/master/meetings/2017/LDM-2017-09-27.mdhttps://github.com/dotnet/csharplang/blob/master/meetings/2017/LDM-2017-02-22.md https://github.com/dotnet/csharplang/blob/master/meetings/2017/LDM-2017-03-01.md https://github.com/dotnet/csharplang/blob/master/meetings/2017/LDM-2017-08-28.md https://github.com/dotnet/csharplang/blob/master/meetings/2017/LDM-2017-09-25.md https://github.com/dotnet/csharplang/blob/master/meetings/2017/LDM-2017-09-27.md