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/8374
Özet
paramsile daha tutarlı hale getirmek ve mevcut belirsizlik senaryolarını daha iyi ele almak için dönüştürme kurallarının güncellemeleri. Örneğin, ReadOnlySpan<string> vs ReadOnlySpan<object> şu anda [""]için aşırı yükleme çözümlemesi sırasında belirsizliklere neden olabilir.
Ayrıntılı Tasarım
İfade kurallarının daha iyi dönüşümleri aşağıdadır. Bunlar, https://github.com/dotnet/csharplang/blob/main/proposals/csharp-12.0/collection-expressions.md#overload-resolutioniçindeki kuralların yerini alır.
Bu kurallar şunlardır:
bir ifadeden
türüne dönüştüren örtük dönüştürme ve bir ifadeden türüne dönüştüren örtük dönüştürme göz önünde bulundurulduğunda, eğer aşağıdakilerden biri geçerliyse, de daha iyi bir dönüştürme bir :
, bir koleksiyon ifadesidir ve , ifade daha iyi bir koleksiyon dönüştürme işlemidir bir koleksiyon ifadesi değildir ve aşağıdakilerden biri geçerlidir:
E,T₁ile tam olarak eşleşir veE,T₂ile tam olarak eşleşmez.E,T₁veT₂'nin her ikisiyle de veya hiçbiriyle de tam olarak eşleşir veT₁, 'denT₂Ebir yöntem grubudur, ...
ifadesinden daha iyi koleksiyon dönüştürmesi için
Verilen:
-
E,[EL₁, EL₂, ..., ELₙ]öğe ifadeleri içeren bir koleksiyon ifadesidir. -
T₁veT₂koleksiyon türleridir -
E₁T₁öğe türüdür -
E₂T₂öğe türüdür -
CE₁ᵢELᵢ'denE₁dönüştürme dizisidir -
CE₂ᵢELᵢ'denE₂dönüştürme dizisidir
E₁'dan E₂'e birim dönüşümü varsa, öğe dönüşümleri de birbirleri kadar iyidir. Aksi takdirde,
- her
ELᵢiçinCE₁ᵢen azCE₂ᵢkadar iyidir ve -
CE₁ᵢCE₂ᵢ'den daha iyi olduğu en az bir i vardır. Aksi takdirde, öğe dönüştürmeleri kümesi diğerinden daha iyi değildir ve aynı zamanda birbirleri kadar iyi değildir.
Dönüşüm karşılaştırmaları,ELᵢbir spread öğesi değilse ifadeden daha iyi dönüşüm kullanılarak yapılır.ELᵢbir yayılma elemanıysa, yayma koleksiyonunun eleman türündenE₁veyaE₂'ye daha iyi bir dönüşüm kullanırız.
- hem
hem de span türleri değildir, ve örtük olarak dönüştürülebilir, ve için örtük olarak dönüştürülemez, veya 'un 'e bir kimlik dönüşümü yoktur ve 'ye öğe dönüşümleri,'dan 'ye öğe dönüşümlerine göre daha iyidir veya -
E₁E₂kimlik dönüştürmesi vardır ve aşağıdakilerden biri geçerlidir:-
T₁System.ReadOnlySpan<E₁>eşittir, veT₂System.Span<E₂>eşittir, veya -
T₁System.ReadOnlySpan<E₁>veyaSystem.Span<E₁>'dir veT₂, öğe türü olan birE₂'dir.
-
Aksi takdirde, koleksiyon türü daha iyi değildir ve sonuç belirsizdir.
Not
Bu kurallar, farklı öğe türlerini içeren ve koleksiyon türleri arasında bir dönüşüm olmaksızın aşırı yüklemeler sunan yöntemlerin boş koleksiyon ifadeleri için belirsiz olduğunu ifade eder. Örnek olarak:
public void M(ReadOnlySpan<int> ros) { ... }
public void M(Span<int?> span) { ... }
M([]); // Ambiguous
Senaryo:
Düz İngilizce olarak, koleksiyon türlerinin kendileri aynı olmalıdır, veya açıkça daha iyi (örneğin, List<T> ve List<T> aynıdır, List<T>IEnumerable<T>'den kesin olarak daha iyidir ve List<T> ile HashSet<T> karşılaştırılamaz) ve daha iyi koleksiyon türü için öğe dönüştürmeleri de aynı veya daha iyi olmalıdır (yani, ReadOnlySpan<object>için Span<string> ile [""] arasında karar veremeyiz. kullanıcının bu kararı alması gerekir). Bunun diğer örnekleri şunlardır:
T₁ |
T₂ |
E |
C₁ Dönüşümler |
C₂ Dönüşümler |
CE₁ᵢ ile CE₂ᵢ karşılaştırması |
Sonuç |
|---|---|---|---|---|---|---|
List<int> |
List<byte> |
[1, 2, 3] |
[Identity, Identity, Identity] |
[Implicit Constant, Implicit Constant, Implicit Constant] |
CE₁ᵢ daha iyidir |
List<int> seçilir |
List<int> |
List<byte> |
[(int)1, (byte)2] |
[Identity, Implicit Numeric] |
Uygulanamaz |
T₂ uygulanamaz |
List<int> seçilir |
List<int> |
List<byte> |
[1, (byte)2] |
[Identity, Implicit Numeric] |
[Implicit Constant, Identity] |
İkisi de daha iyi değil | Belirsiz |
List<int> |
List<byte> |
[(byte)1, (byte)2] |
[Implicit Numeric, Implicit Numeric] |
[Identity, Identity] |
CE₂ᵢ daha iyidir |
List<byte> seçilir |
List<int?> |
List<long> |
[1, 2, 3] |
[Implicit Nullable, Implicit Nullable, Implicit Nullable] |
[Implicit Numeric, Implicit Numeric, Implicit Numeric] |
İkisi de daha iyi değil | Belirsiz |
List<int?> |
List<ulong> |
[1, 2, 3] |
[Implicit Nullable, Implicit Nullable, Implicit Nullable] |
[Implicit Numeric, Implicit Numeric, Implicit Numeric] |
CE₁ᵢ daha iyidir |
List<int?> seçilir |
List<short> |
List<long> |
[1, 2, 3] |
[Implicit Numeric, Implicit Numeric, Implicit Numeric] |
[Implicit Numeric, Implicit Numeric, Implicit Numeric] |
CE₁ᵢ daha iyidir |
List<short> seçilir |
IEnumerable<int> |
List<byte> |
[1, 2, 3] |
[Identity, Identity, Identity] |
[Implicit Constant, Implicit Constant, Implicit Constant] |
CE₁ᵢ daha iyidir |
IEnumerable<int> seçilir |
IEnumerable<int> |
List<byte> |
[(byte)1, (byte)2] |
[Implicit Numeric, Implicit Numeric] |
[Identity, Identity] |
CE₂ᵢ daha iyidir |
List<byte> seçilir |
int[] |
List<byte> |
[1, 2, 3] |
[Identity, Identity, Identity] |
[Implicit Constant, Implicit Constant, Implicit Constant] |
CE₁ᵢ daha iyidir |
int[] seçilir |
ReadOnlySpan<string> |
ReadOnlySpan<object> |
["", "", ""] |
[Identity, Identity, Identity] |
[Implicit Reference, Implicit Reference, Implicit Reference] |
CE₁ᵢ daha iyidir |
ReadOnlySpan<string> seçilir |
ReadOnlySpan<string> |
ReadOnlySpan<object> |
["", new object()] |
Uygulanamaz | [Implicit Reference, Identity] |
T₁ uygulanamaz |
ReadOnlySpan<object> seçilir |
ReadOnlySpan<object> |
Span<string> |
["", ""] |
[Implicit Reference] |
[Identity] |
CE₂ᵢ daha iyidir |
Span<string> seçilir |
ReadOnlySpan<object> |
Span<string> |
[new object()] |
[Identity] |
Uygulanamaz |
T₁ uygulanamaz |
ReadOnlySpan<object> seçilir |
ReadOnlySpan<InterpolatedStringHandler> |
ReadOnlySpan<string> |
[$"{1}"] |
[Interpolated String Handler] |
[Identity] |
CE₁ᵢ daha iyidir |
ReadOnlySpan<InterpolatedStringHandler> seçilir |
ReadOnlySpan<InterpolatedStringHandler> |
ReadOnlySpan<string> |
[$"{"blah"}"] |
[Interpolated String Handler] |
[Identity] - Ancak sabit |
CE₂ᵢ daha iyidir |
ReadOnlySpan<string> seçilir |
ReadOnlySpan<string> |
ReadOnlySpan<FormattableString> |
[$"{1}"] |
[Identity] |
[Interpolated String] |
CE₂ᵢ daha iyidir |
ReadOnlySpan<string> seçilir |
ReadOnlySpan<string> |
ReadOnlySpan<FormattableString> |
[$"{1}", (FormattableString)null] |
Uygulanamaz | [Interpolated String, Identity] |
T₁ uygulanamaz |
ReadOnlySpan<FormattableString> seçilir |
HashSet<short> |
Span<long> |
[1, 2] |
[Implicit Constant, Implicit Constant] |
[Implicit Numeric, Implicit Numeric] |
CE₁ᵢ daha iyidir |
HashSet<short> seçilir |
HashSet<long> |
Span<short> |
[1, 2] |
[Implicit Numeric, Implicit Numeric] |
[Implicit Constant, Implicit Constant] |
CE₂ᵢ daha iyidir |
Span<short> seçilir |
Açık sorular
ReadOnlySpan
/
Span diğer türlere göre ne kadar önceliklendirmemiz gerekir?
Bugün belirtildiği gibi, aşağıdaki aşırı yüklemeler belirsiz olacaktır:
C.M1(["Hello world"]); // Ambiguous, no tiebreak between ROS and List
C.M2(["Hello world"]); // Ambiguous, no tiebreak between Span and List
C.M3(["Hello world"]); // Ambiguous, no tiebreak between ROS and MyList.
C.M4(["Hello", "Hello"]); // Ambiguous, no tiebreak between ROS and HashSet. Created collections have different contents
class C
{
public static void M1(ReadOnlySpan<string> ros) {}
public static void M1(List<string> list) {}
public static void M2(Span<string> ros) {}
public static void M2(List<string> list) {}
public static void M3(ReadOnlySpan<string> ros) {}
public static void M3(MyList<string> list) {}
public static void M4(ReadOnlySpan<string> ros) {}
public static void M4(HashSet<string> hashset) {}
}
class MyList<T> : List<T> {}
Buraya ne kadar gitmek istiyoruz?
List<T> değişkeni mantıklı görünüyor ve List<T>'in birçok alt türü mevcut. Ancak HashSet sürümünün çok farklı bir semantiği var, bu API'de gerçekten ReadOnlySpan'den daha kötü olduğundan ne kadar eminiz?
C# feature specifications