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.
Bu belgede, .NET 6 genel sürümünden (.NET SDK sürüm 6.0.100) .NET 7 genel sürümüne (.NET SDK sürüm 7.0.100) kadar Roslyn'deki bilinen uyumsuzluk değişiklikleri listelenir.
Zaman uyumsuz metotlar içinde kısıtlanmış türlere sahip tüm yerel değişkenlere izin verilmiyor
Visual Studio 2022 sürüm 17.6p1 ile kullanıma sunulmuştur
Kısıtlı türlerdeki yerel değişkenlere zaman uyumsuz yöntemlerde izin verilmez. Ancak önceki sürümlerde derleyici örtük olarak bildirilen bazı yerel öğeleri farkedemedi. Örneğin, foreach
veya using
deyimleri ya da çözümlemeler içinde.
Şimdi, bu örtük olarak bildirilen yerel değişkenlere de izin verilmiyor.
ref struct RefStruct { public void Dispose() { } }
public class C
{
public async Task M()
{
RefStruct local = default; // disallowed
using (default(RefStruct)) { } // now disallowed too ("error CS9104: A using statement resource of this type cannot be used in async methods or async lambda expressions")
}
}
Bkz. https://github.com/dotnet/roslyn/pull/66264
İşaretçiler her zaman güvenli olmayan bağlamlarda olmalıdır.
Visual Studio 2022 sürüm 17.6'da kullanıma sunulmuştur
Önceki SDK'larda, derleyici ara sıra işaretçilerin başvurulabileceği konumlara, o konumu açıkça güvensiz olarak işaretlemeden izin verirdi.
Değiştiricinin unsafe
mevcut olması gerekir.
Örneğin using Alias = List<int*[]>;
, yasal olacak şekilde using unsafe Alias = List<int*[]>;
değiştirilmelidir.
"void Method(Alias a) ...
gibi bir kullanım, unsafe void Method(Alias a) ...
olarak değiştirilmelidir."
Kural, using
diğer ad bildirimleri dışında koşulsuzdur (bu, C# 12 öncesinde unsafe
değiştiriciye izin vermiyordu).
Bu nedenle, bildirimler için using
kural yalnızca dil sürümü C# 12 veya üzeri olarak seçilirse geçerlilik kazanır.
System.TypedReference yönetilen kod olarak kabul edilir
Visual Studio 2022 sürüm 17.6'da kullanıma sunulmuştur
İlerleyen dönemde System.TypedReference
tipi yönetilen olarak kabul edilecektir.
unsafe
{
TypedReference* r = null; // warning: This takes the address of, gets the size of, or declares a pointer to a managed type
var a = stackalloc TypedReference[1]; // error: Cannot take the address of, get the size of, or declare a pointer to a managed type
}
Referans güvenliği hataları, lambda ifadesinden temsilciye dönüşümü etkilemez
Visual Studio 2022 sürüm 17.5'te kullanıma sunulmuştur
Lambda gövdesinde bildirilen referans güvenliği hataları artık lambda ifadesinin temsilci türüne dönüştürülebilir olup olmadığını etkilemez. Bu değişiklik aşırı yükleme çözümünü etkileyebilir.
Aşağıdaki örnekte, Visual Studio 17.5 ile M(x => ...)
çağrısı belirsizdir, çünkü artık hem M(D1)
hem de M(D2)
geçerli kabul edilmektedir. Oysa lambda gövdesi içindeki F(ref x, ref y)
çağrısı, M(D1)
'ın güvenliğine neden olacaktır (karşılaştırma için d1
ve d2
içindeki örneklere bakın). Daha önce, M(D1)
aşırı yüklemesinin geçerli olmadığı kabul edildiğinden çağrı açık bir şekilde M(D2)
ile ilişkilendiriliyordu.
using System;
ref struct R { }
delegate R D1(R r);
delegate object D2(object o);
class Program
{
static void M(D1 d1) { }
static void M(D2 d2) { }
static void F(ref R x, ref Span<int> y) { }
static void F(ref object x, ref Span<int> y) { }
static void Main()
{
// error CS0121: ambiguous between: 'M(D1)' and 'M(D2)'
M(x =>
{
Span<int> y = stackalloc int[1];
F(ref x, ref y);
return x;
});
D1 d1 = x1 =>
{
Span<int> y1 = stackalloc int[1];
F(ref x1, ref y1); // error CS8352: 'y2' may expose referenced variables
return x1;
};
D2 d2 = x2 =>
{
Span<int> y2 = stackalloc int[1];
F(ref x2, ref y2); // ok: F(ref object x, ref Span<int> y)
return x2;
};
}
}
Aşırı yük çözümleme değişikliklerine geçici bir çözüm olarak, lambda parametreleri veya temsilci fonksiyon/delege için açık türler kullanın.
// ok: M(D2)
M((object x) =>
{
Span<int> y = stackalloc int[1];
F(ref x, ref y); // ok: F(ref object x, ref Span<int> y)
return x;
});
Satırın başında ham dize ilişkilendirmeleri.
Visual Studio 2022 sürüm 17.5'te kullanıma sunulmuştur
.NET SDK 7.0.100 veya önceki sürümlerinde aşağıdakilere yanlışlıkla izin verildi:
var x = $"""
Hello
{1 + 1}
World
""";
Bu, satır içeriğinin (ilişkilendirmenin başladığı yer dahil) son """;
satırla aynı boşlukla başlaması gerektiği kuralını ihlal etti. Yukarıdakilerin şu şekilde yazılması gerekir:
var x = $"""
Hello
{1 + 1}
World
""";
Yöntemler için çıkarsanan temsilci türü varsayılan parametre değerlerini ve params
değiştiriciyi içerir
Visual Studio 2022 sürüm 17.5'te kullanıma sunulmuştur
.NET SDK 7.0.100 veya daha önceki sürümlerinde, yöntemlerden çıkarılan temsilci türleri, aşağıdaki kodda gösterildiği gibi, varsayılan parametre değerlerini ve params
değiştiricilerini göz ardı ederdi.
void Method(int i = 0, params int[] xs) { }
var action = Method; // System.Action<int, int[]>
DoAction(action, 1); // ok
void DoAction(System.Action<int, int[]> a, int p) => a(p, new[] { p });
.NET SDK 7.0.200 veya sonraki sürümlerinde, bu tür yöntemler aynı varsayılan parametre değerlerine ve params
değiştiricilere sahip anonim sentezlenmiş temsilci türleri olarak çıkarılır.
Bu değişiklik, aşağıda gösterildiği gibi yukarıdaki kodu bozabilir:
void Method(int i = 0, params int[] xs) { }
var action = Method; // delegate void <anonymous delegate>(int arg1 = 0, params int[] arg2)
DoAction(action, 1); // error CS1503: Argument 1: cannot convert from '<anonymous delegate>' to 'System.Action<int, int[]>'
void DoAction(System.Action<int, int[]> a, int p) => a(p, new[] { p });
İlişkili teklifte bu değişiklik hakkında daha fazla bilgi edinebilirsiniz.
Kesin atama analizi amacıyla, async yerel işlevlerin çağrıları artık bekleniyor gibi değerlendirilmemektedir.
Visual Studio 2022 sürüm 17.5'te kullanıma sunulmuştur
Kesin atama analizi amacıyla, zaman uyumsuz bir yerel işlevin çağrıları artık beklenmiş olarak ele alınmaz ve bu nedenle yerel işlev tam olarak gerçekleştirilmiş olarak kabul edilmez. Rasyonalite için bkz https://github.com/dotnet/roslyn/issues/43697 .
Aşağıdaki kod artık kesin bir atama hatası bildirecek:
public async Task M()
{
bool a;
await M1();
Console.WriteLine(a); // error CS0165: Use of unassigned local variable 'a'
async Task M1()
{
if ("" == String.Empty)
{
throw new Exception();
}
else
{
a = true;
}
}
}
INoneOperation
öznitelik düğümleri artık IAttributeOperation
düğümlerdir.
Visual Studio 2022 sürüm 17.5, .NET SDK sürüm 7.0.200 ile kullanıma sunulmuştur
Derleyicinin önceki sürümlerinde, özniteliğe ait IOperation
ağacı, INoneOperation
düğümüyle köklendirildi.
Öznitelikler için yerel destek ekledik, bu da ağacın kökünün artık bir IAttributeOperation
olduğu anlamına gelir. .NET SDK çözümleyicilerinin eski sürümleri de dahil olmak üzere bazı çözümleyiciler bu ağaç şeklini beklemiyor ve karşılaştığında yanlış bir uyarıda bulunabilir (veya uyarı vermeyebilir). Bunun geçici çözümleri şunlardır:
- Mümkünse çözümleyici sürümünüzü güncelleştirin. .NET SDK'sını veya Microsoft.CodeAnalysis.FxCopAnalyzers'in eski sürümlerini kullanıyorsanız Microsoft.CodeAnalysis.NetAnalyzers 7.0.0-preview1.22464.1 veya daha yeni bir sürüme güncelleştirin.
- Çözümleyicilerden gelen hatalı pozitif sonuçları, bu değişikliği dikkate alan bir sürümle güncellenene kadar gizleyin.
Yapılar için ref
tür testleri desteklenmez.
Visual Studio 2022 sürüm 17.4'te kullanıma sunulmuştur
Yapı ref
türü 'is' veya 'as' işlecinde kullanıldığında, bazı senaryolarda derleyici daha önce çalışma zamanında her zaman başarısız olan tür testiyle ilgili hatalı bir uyarı bildirmiş, gerçek tür denetimini atlamış ve yanlış davranışa yol açıyordu. Yürütme zamanında yanlış davranış mümkün olduğunda, derleyici artık bunun yerine bir hata oluşturur.
ref struct G<T>
{
public void Test()
{
if (this is G<int>) // Will now produce an error, used to be treated as always `false`.
{
Yerel ref'den kullanılmayan sonuçlar işaretçiden kaldırılır.
Visual Studio 2022 sürüm 17.4'te kullanıma sunulmuştur
ref
Yerel değişken bir değere göre referans alınıp ancak sonuç kullanılmadığında (örneğin bir atmaya atanması durumunda), sonuç önceki zamanlarda görmezden gelinmişti. Derleyici artık yerel olarak başvurarak herhangi bir yan etkinin gözlemlenmesine dikkat edecektir.
ref int local = Unsafe.NullRef<int>();
_ = local; // Will now produce a `NullReferenceException`
Türler adlandırılamaz scoped
Visual Studio 2022 sürüm 17.4'te kullanıma sunulmuştur. C# 11'den başlayarak türler olarak adlandırılamaz scoped
. Derleyici, bu türdeki tüm adlarda bir hata bildirecektir. Bu sorunu geçici olarak çözmek için tür adı ve tüm kullanımların bir @
ile kaçışı yapılmalıdır:
class scoped {} // Error CS9056
class @scoped {} // No error
ref scoped local; // Error
ref scoped.nested local; // Error
ref @scoped local2; // No error
Bu, artık değişken bildirimleri için bir değiştirici olduğundan ve ref
bir ref türünde takip edildiğinden scoped
olarak yapıldı.
Türler adlandırılamaz file
Visual Studio 2022 sürüm 17.4'te kullanıma sunulmuştur. C# 11'den başlayarak türler olarak adlandırılamaz file
. Derleyici, bu türdeki tüm adlarda bir hata bildirecektir. Bu sorunu geçici olarak çözmek için tür adı ve tüm kullanımların bir @
ile kaçışı yapılmalıdır:
class file {} // Error CS9056
class @file {} // No error
Bu, artık tür bildirimleri için bir değiştirici olduğu file
için yapıldı.
İlişkili csharplang sorununda bu değişiklik hakkında daha fazla bilgi edinebilirsiniz.
#line span yönergelerinde gerekli alanlar
.NET SDK 6.0.400, Visual Studio 2022 sürüm 17.3 ile kullanıma sunulmuştur.
Span yönergesi #line
C# 10'da kullanıma sunulduğunda belirli bir aralık gerektirmedi.
Örneğin, bu geçerli olacaktır: #line(1,2)-(3,4)5"file.cs"
.
Visual Studio 17.3'te, derleyici ilk parantezden önce boşluklar, karakter uzaklığı ve dosya adı gerektirir.
Bu nedenle, yukarıdaki örnek boşluk eklenmediği sürece ayrıştırılamaz: #line (1,2)-(3,4) 5 "file.cs"
.
System.IntPtr ve System.UIntPtr üzerinde denetlenen işleçler
.NET SDK 7.0.100, Visual Studio 2022 sürüm 17.3 ile kullanıma sunulmuştur.
Platform sayısalIntPtr
ve UIntPtr
türleri desteklediğinde (varlığının System.Runtime.CompilerServices.RuntimeFeature.NumericIntPtr
gösterdiği gibi) yerleşik işleçler nint
ve nuint
bu temel türler için geçerlidir.
Bu, bu tür platformlarda IntPtr
checked
ve UIntPtr
yerleşik işleçlere sahip olduğu ve artık taşma oluştuğunda oluşturabileceği anlamına gelir.
IntPtr M(IntPtr x, int y)
{
checked
{
return x + y; // may now throw
}
}
unsafe IntPtr M2(void* ptr)
{
return checked((IntPtr)ptr); // may now throw
}
Olası geçici çözümler şunlardır:
- Bağlamı belirt
unchecked
- Sayısal
IntPtr
/UIntPtr
türleri olmayan bir platforma/TFM'ye düşürme
Ayrıca, IntPtr
/UIntPtr
ile diğer sayısal türler arasındaki örtük dönüştürmeler, bu tür platformlarda standart dönüştürmeler olarak kabul edilir. Bu, bazı durumlarda aşırı yükleme çözümünü etkileyebilir.
Bu değişiklikler, kullanıcı kodu denetlenmeyen bir bağlamda taşma özel durumlarına bağlıysa veya denetlenen bir bağlamda taşma özel durumları beklemiyorsa davranış değişikliğine neden olabilir. Bu tür davranış değişikliklerini algılamaya ve uygun eylemleri gerçekleştirmeye yardımcı olmak için 7.0'da bir çözümleyici eklendi. Çözümleyici, varsayılan olarak bilgi önem derecesine sahip olan ancak editorconfig aracılığıyla uyarılara yükseltilebilen olası davranış değişiklikleriyle ilgili tanılamalar oluşturur.
System.UIntPtr ve System.Int32'nin Eklenmesi
.NET SDK 7.0.100, Visual Studio 2022 sürüm 17.3 ile kullanıma sunulmuştur.
Platform sayısalIntPtr
ve UIntPtr
türleri desteklediğinde (varlığı System.Runtime.CompilerServices.RuntimeFeature.NumericIntPtr
gösterildiğinden), System.UIntPtr
içinde tanımlanan işleç +(UIntPtr, int)
artık kullanılamaz.
Bunun yerine, System.UIntPtr
ve System.Int32
türlerinin ifadelerini eklemek bir hataya neden olur:
UIntPtr M(UIntPtr x, int y)
{
return x + y; // error: Operator '+' is ambiguous on operands of type 'nuint' and 'int'
}
Olası geçici çözümler şunlardır:
-
UIntPtr.Add(UIntPtr, int)
Yöntemini kullanın:UIntPtr.Add(x, y)
- İkinci işleme
nuint
üzerinde kontrolsüz tür dönüşümü uygulayın:x + unchecked((nuint)y)
Bir yöntemde veya yerel işlevde öznitelik olarak Nameof işleci
.NET SDK 6.0.400, Visual Studio 2022 sürüm 17.3 ile kullanıma sunulmuştur.
Dil sürümü C# 11 veya üzeri olduğunda, nameof
bir yöntemdeki bir öznitelikteki işleç, bu yöntemin tür parametrelerini kapsama getirir. Aynı durum yerel işlevler için de geçerlidir.
Bir yöntemdeki bir öznitelikte nameof
işleci, tür parametreleri veya parametreleri, o yöntemin parametrelerini kapsam içine alır. Aynı durum yerel işlevler, lambdalar, temsilciler ve dizin oluşturucular için de geçerlidir.
Örneğin, bunlar artık hatalar olacaktır:
class C
{
class TParameter
{
internal const string Constant = """";
}
[MyAttribute(nameof(TParameter.Constant))]
void M<TParameter>() { }
}
class C
{
class parameter
{
internal const string Constant = """";
}
[MyAttribute(nameof(parameter.Constant))]
void M(int parameter) { }
}
Olası geçici çözümler şunlardır:
- Adın dış kapsamdan gölgelenmesinden kaçınmak için tür parametresini veya parametresini yeniden adlandırın.
-
nameof
işleci yerine dize literalı kullanın.
Referans olarak bir out parametresi döndürülemez
.NET SDK 7.0.100, Visual Studio 2022 sürüm 17.3 ile kullanıma sunulmuştur.
C# 11 veya sonraki bir dil sürümüyle ya da .NET 7.0 veya daha sonraki bir sürümle, out
adlı bir parametre referans olarak döndürülemez.
static ref T ReturnOutParamByRef<T>(out T t)
{
t = default;
return ref t; // error CS8166: Cannot return a parameter by reference 't' because it is not a ref parameter
}
Olası geçici çözümler şunlardır:
"Başvuruyu kapsamsız olarak işaretlemek için
System.Diagnostics.CodeAnalysis.UnscopedRefAttribute
kullanın."static ref T ReturnOutParamByRef<T>([UnscopedRef] out T t) { t = default; return ref t; // ok }
Parametreyi
ref
ile geçirmek için yöntem imzasını değiştirin.static ref T ReturnRefParamByRef<T>(ref T t) { t = default; return ref t; // ok }
ref yapıdaki örnek metodu, kapsamsız ref parametrelerini bağlayabilir
.NET SDK 7.0.100, Visual Studio 2022 sürüm 17.4 ile kullanıma sunulmuştur.
C# 11 veya sonraki bir dil sürümüyle ya da .NET 7.0 veya sonraki bir sürümle, kapsamsız ref
veya in
parametreleri yakalamak için bir ref struct
örnek yöntemi çağrısı varsayılır.
R<int> Use(R<int> r)
{
int i = 42;
r.MayCaptureArg(ref i); // error CS8350: may expose variables referenced by parameter 't' outside of their declaration scope
return r;
}
ref struct R<T>
{
public void MayCaptureArg(ref T t) { }
}
Eğer ref
veya in
parametresi ref struct
örnek yönteminde yakalanmazsa, olası bir geçici çözüm, parametreyi scoped ref
veya scoped in
olarak bildirmektir.
R<int> Use(R<int> r)
{
int i = 42;
r.CannotCaptureArg(ref i); // ok
return r;
}
ref struct R<T>
{
public void CannotCaptureArg(scoped ref T t) { }
}
Bağlamsal yapı referans dönüş kaçışı analizi, referans bağımsız değişkenlerinin referans kaçışına bağlıdır.
.NET SDK 7.0.100, Visual Studio 2022 sürüm 17.4 ile kullanıma sunulmuştur.
C# 11 veya sonraki bir dil sürümüyle ya da .NET 7.0 veya sonraki bir sürümüyle, ref struct
dönüş değeri olarak veya out
parametrelerde bir yöntem çağrısından döndürülen bir değer yalnızca, yöntem çağrısında yer alan ref
ve in
tüm bağımsız değişkenlerin ref-kaçışı güvenli olması durumunda kaçışı güvenlidir.
in
Bağımsız değişkenler örtük varsayılan parametre değerlerini içerebilir.
ref struct R { }
static R MayCaptureArg(ref int i) => new R();
static R MayCaptureDefaultArg(in int i = 0) => new R();
static R Create()
{
int i = 0;
// error CS8347: Cannot use a result of 'MayCaptureArg(ref int)' because it may expose
// variables referenced by parameter 'i' outside of their declaration scope
return MayCaptureArg(ref i);
}
static R CreateDefault()
{
// error CS8347: Cannot use a result of 'MayCaptureDefaultArg(in int)' because it may expose
// variables referenced by parameter 'i' outside of their declaration scope
return MayCaptureDefaultArg();
}
Eğer ref
veya in
bağımsız değişkeni ref struct
dönüş değerinde yakalanmazsa, olası bir geçici çözüm parametreyi scoped ref
veya scoped in
olarak bildirmektir.
static R CannotCaptureArg(scoped ref int i) => new R();
static R Create()
{
int i = 0;
return CannotCaptureArg(ref i); // ok
}
ref
ile ref struct
bağımsız değişken __arglist
içinde kapsam dışı olarak düşünülen
.NET SDK 7.0.100, Visual Studio 2022 sürüm 17.4 ile kullanıma sunulmuştur.
C# 11 veya daha sonraki bir dil sürümüyle veya .NET 7.0 veya sonraki bir sürümle, bir ref
türü bir __arglist
'ye bağımsız değişken olarak geçirildiğinde, kapsamsız bir başvuru olarak kabul edilir.
ref struct R { }
class Program
{
static void MayCaptureRef(__arglist) { }
static void Main()
{
var r = new R();
MayCaptureRef(__arglist(ref r)); // error: may expose variables outside of their declaration scope
}
}
İmzasız sağ kaydırma işleci
.NET SDK 6.0.400, Visual Studio 2022 sürüm 17.3 ile kullanıma sunulmuştur. Dil, "İmzasız Sağ Shift" işleci (>>>
) için destek ekledi.
Bu, kullanıcı tanımlı "İmzasız Sağ Kaydırma" işleçlerini normal yöntemler olarak uygulayan yöntemleri kullanma özelliğini devre dışı bırakır.
Örneğin, bir dilde (VB veya C# dışında) geliştirilen ve türü C1
için "İmzasız Sağ Kaydırma" kullanıcı tanımlı işlecini kullanıma sunan mevcut bir kütüphane vardır.
Aşağıdaki kod daha önce başarıyla derleniyordu.
static C1 Test1(C1 x, int y) => C1.op_UnsignedRightShift(x, y); //error CS0571: 'C1.operator >>>(C1, int)': cannot explicitly call operator or accessor
Olası bir geçici çözüm, >>>
operatörünü kullanmaya geçmektir.
static C1 Test1(C1 x, int y) => x >>> y;
Başvuru yapısı olarak Foreach numaralandırıcısı
.NET SDK 6.0.300, Visual Studio 2022 sürüm 17.2 ile kullanıma sunulmuştur.foreach
Başvuru yapısı numaralandırıcı türü kullanan bir, dil sürümü 7.3 veya daha önceki bir sürüme ayarlanmışsa hata bildirir.
Bu, özelliğin desteklenmeden önce C# sürümünü hedefleyen daha yeni derleyicilerde desteklendiği bir hatayı düzeltir.
Olası geçici çözümler şunlardır:
-
ref struct
türünü birstruct
veyaclass
türüne değiştirin. -
<LangVersion>
öğesini 7.3 veya sonraki bir sürüme yükseltin.
Async foreach
, IAsyncDisposable.DisposeAsync()
'nin açık arabirim uygulamasına göre desen tabanlı DisposeAsync
tercih eder
.NET SDK 6.0.300, Visual Studio 2022 sürüm 17.2 ile kullanıma sunulmuştur. Zaman uyumsuz foreach
, IAsyncDisposable.DisposeAsync()
yerine desen tabanlı bir DisposeAsync()
yöntemini kullanarak bağlanmayı tercih eder.
Örneğin , DisposeAsync()
üzerindeki AsyncEnumerator
yöntemi yerine IAsyncEnumerator<int>.DisposeAsync()
seçilir:
await foreach (var i in new AsyncEnumerable())
{
}
struct AsyncEnumerable
{
public AsyncEnumerator GetAsyncEnumerator() => new AsyncEnumerator();
}
struct AsyncEnumerator : IAsyncDisposable
{
public int Current => 0;
public async ValueTask<bool> MoveNextAsync()
{
await Task.Yield();
return false;
}
public async ValueTask DisposeAsync()
{
Console.WriteLine("PICKED");
await Task.Yield();
}
ValueTask IAsyncDisposable.DisposeAsync() => throw null; // no longer picked
}
Bu değişiklik, ortak DisposeAsync
yöntemin bildirilen tür üzerinde görünür olduğu bir belirtim ihlalini düzeltirken, açık arabirim uygulaması yalnızca arabirim türüne başvuru kullanılarak görülebilir.
Bu hataya geçici bir çözüm olarak, desen tabanlı DisposeAsync
yöntemi türünüzden kaldırın.
Dönüştürülen dizeleri altsayılan bağımsız değişken olarak yasakla
.NET SDK 6.0.300, Visual Studio 2022 sürüm 17.2 ile kullanıma sunulmuştur. C# derleyicisi, bir dize sabitinin başvuru dönüştürmesini içeren yanlış varsayılan bağımsız değişken değerlerini kabul eder ve kaynakta belirtilen varsayılan değer yerine sabit değer olarak yayar null
. Visual Studio 17.2'de bu bir hataya dönüşür. Bkz. roslyn#59806.
Bu değişiklik derleyicideki belirtim ihlalini düzeltir. Varsayılan bağımsız değişkenler derleme zamanı sabitleri olmalıdır. Önceki sürümler aşağıdaki koda izin verdirdi:
void M(IEnumerable<char> s = "hello")
Önceki bildirim, string
'den IEnumerable<char>
'e bir dönüşüm gerektiriyordu. Derleyici bu yapıya izin verdi ve bağımsız değişkenin değeri olarak null
'i üretti. Yukarıdaki kod, 17.2'den başlayarak bir derleyici hatası oluşturur.
Bu değişikliği geçici olarak çözmek için aşağıdaki değişikliklerden birini yapabilirsiniz:
- Dönüştürme gerekmemesi için parametre türünü değiştirin.
- Önceki davranışı geri yüklemek için varsayılan bağımsız değişkenin
null
değerini olarak değiştirin.
Açık lambda dönüş türü olarak bağlamsal anahtar sözcük var
.NET SDK 6.0.200, Visual Studio 2022 sürüm 17.1 ile kullanıma sunulmuştur. Bağlamsal anahtar sözcük var açık lambda dönüş türü olarak kullanılamaz.
Bu değişiklik, lambda ifadesinin var
dönüş türü için doğal tür olarak kalmasını sağlayarak gelecekteki olası özellikleri etkinleştirir.
Adlı var
bir türünüz varsa ve açık dönüş türünü var
(türü) kullanarak bir lambda ifadesi tanımlıyorsanız bu hatayla karşılaşabilirsiniz.
using System;
F(var () => default); // error CS8975: The contextual keyword 'var' cannot be used as an explicit lambda return type
F(@var () => default); // ok
F(() => default); // ok: return type is inferred from the parameter to F()
static void F(Func<var> f) { }
public class var
{
}
Geçici çözümler aşağıdaki değişiklikleri içerir:
- Dönüş türü olarak kullanın
@var
. - Derleyicinin dönüş türünü belirlemesi için açık dönüş türünü kaldırın.
Ara dize işleyicileri ve indeks başlatma
.NET SDK 6.0.200, Visual Studio 2022 sürüm 17.1 ile kullanıma sunulmuştur. Ara dize işleyicisi alan ve alıcıyı giriş olarak gerektiren dizinleyiciler, nesne başlatıcıda kullanılamaz.
Bu değişiklik, dizin oluşturucu başlatıcılarının ilişkilendirilmiş bir dize işleyicisi kullandığı ve ilişkilendirilmiş dize işleyicisinin dizin oluşturucunun alıcısını oluşturucunun parametresi olarak aldığı bir uç durum senaryosuna izin vermemektedir. Bu değişikliğin nedeni, bu senaryonun henüz başlatılmamış değişkenlere erişmesine neden olmasıdır. Şu örneği göz önünde bulundurun:
using System.Runtime.CompilerServices;
// error: Interpolated string handler conversions that reference
// the instance being indexed cannot be used in indexer member initializers.
var c = new C { [$""] = 1 };
class C
{
public int this[[InterpolatedStringHandlerArgument("")] CustomHandler c]
{
get => ...;
set => ...;
}
}
[InterpolatedStringHandler]
class CustomHandler
{
// The constructor of the string handler takes a "C" instance:
public CustomHandler(int literalLength, int formattedCount, C c) {}
}
Geçici çözümler aşağıdaki değişiklikleri içerir:
- Alıcı türünü interpolasyonlu dize işleyicisinden kaldırın.
- Dizinleyicide kullanılan bağımsız değişkeni "
string
" olarak değiştirin.
ref, readonly ref, in, out parametre veya dönüş değeri olarak, yalnızca yönetilmeyen çağrı yapanlara sahip yöntemlerde kullanılamaz.
.NET SDK 6.0.200, Visual Studio 2022 sürüm 17.1 ile kullanıma sunulmuştur.ref
/ref readonly
/in
/out
ile UnmanagedCallersOnly
ilişkilendirilen bir yöntemin dönüşlerinde/parametrelerinde kullanılmasına izin verilmez.
Bu değişiklik bir hata düzeltmesidir. Dönüş değerleri ve parametreler doğrudan bellek aktarılabilir değildir. Bağımsız değişkenlerin veya dönüş değerlerinin referans ile geçirilmesi tanımsız davranışa neden olabilir. Aşağıdaki bildirimlerden hiçbiri derlenmemiştir:
using System.Runtime.InteropServices;
[UnmanagedCallersOnly]
static ref int M1() => throw null; // error CS8977: Cannot use 'ref', 'in', or 'out' in a method attributed with 'UnmanagedCallersOnly'.
[UnmanagedCallersOnly]
static ref readonly int M2() => throw null; // error CS8977: Cannot use 'ref', 'in', or 'out' in a method attributed with 'UnmanagedCallersOnly'.
[UnmanagedCallersOnly]
static void M3(ref int o) => throw null; // error CS8977: Cannot use 'ref', 'in', or 'out' in a method attributed with 'UnmanagedCallersOnly'.
[UnmanagedCallersOnly]
static void M4(in int o) => throw null; // error CS8977: Cannot use 'ref', 'in', or 'out' in a method attributed with 'UnmanagedCallersOnly'.
[UnmanagedCallersOnly]
static void M5(out int o) => throw null; // error CS8977: Cannot use 'ref', 'in', or 'out' in a method attributed with 'UnmanagedCallersOnly'.
Geçici çözüm, başvuru değiştiricisini kaldırmaktır.
Uzunluk, Sayı desenlerde negatif değil olarak kabul edilir
.NET SDK 6.0.200, Visual Studio 2022 sürüm 17.1 ile kullanıma sunulmuştur.Length
ve Count
sayılabilir ve dizinlenebilir türlerdeki özelliklerin, desenlerin ve anahtarların alt ve kapsamlı analizi amacıyla negatif olmayan olduğu varsayılır.
Bu türler örtük Index dizinleyici ve liste kalıplarıyla kullanılabilir.
Length
ve Count
özellikleri, yazı türü int
olsa da desenleri analiz ederken pozitif olduğu varsayılır. Şu örnek yöntemi göz önünde bulundurun:
string SampleSizeMessage<T>(IList<T> samples)
{
return samples switch
{
// This switch arm prevents a warning before 17.1, but will never happen in practice.
// Starting with 17.1, this switch arm produces a compiler error.
// Removing it won't introduce a warning.
{ Count: < 0 } => throw new InvalidOperationException(),
{ Count: 0 } => "Empty collection",
{ Count: < 5 } => "Too small",
{ Count: < 20 } => "reasonable for the first pass",
{ Count: < 100 } => "reasonable",
{ Count: >= 100 } => "fine",
};
}
void M(int[] i)
{
if (i is { Length: -1 }) {} // error: impossible under assumption of non-negative length
}
17.1'den önce, tüm olası değerlerin kapsanmadığı uyarısını önlemek için birinci anahtar kolunun negatif olduğunu test etmek gerekliydi. 17.1'den başlayarak, ilk anahtar kolu bir derleyici hatası oluşturur. Geçici çözüm, geçersiz durumlar için eklenen anahtar kollarını kaldırmaktır.
Bu değişiklik, liste desenleri eklemenin bir parçası olarak yapılmıştır. Bir koleksiyonda bir Length
veya Count
özelliğinin her kullanımı negatif değil olarak kabul edilirse, işleme kuralları daha tutarlı olur.
Dil tasarımı sorunundaki değişiklikle ilgili diğer ayrıntıları okuyabilirsiniz.
Geçici çözüm, ulaşılamayan koşullarla anahtar kollarını kaldırmaktır.
Bir yapıya alan başlatıcıları eklemek için açıkça bildirilen bir oluşturucu gerekir
.NET SDK 6.0.200, Visual Studio 2022 sürüm 17.1 ile kullanıma sunulmuştur.struct
alan başlatıcıları olan tür bildirimleri açıkça bildirilen bir oluşturucu içermelidir. Ayrıca, başlatıcısı olmayan struct
örnek oluşturucularında tüm alanlar mutlaka atanmalıdır, bu yüzden daha önce atanmamış alanların eklenen oluşturucudan veya alan başlatıcılarıyla atanması gerekir. Bkz. dotnet/csharplang#5552, dotnet/roslyn#58581.
C# dilinde bir değişkeni varsayılan değerine başlatmanın iki yolu vardır: new()
ve default
. Sınıflar için fark belirgindir çünkü new
yeni bir örnek oluşturur ve default
null
döndürür. Yapılar için fark daha inceliklidir, çünkü default
her alan/özellik kendi varsayılan değerine ayarlanmış bir örnek döndürür. C# 10'da yapılar için alan başlatıcıları ekledik. Alan başlatıcıları yalnızca açıkça bildirilen bir oluşturucu çalıştırıldığında yürütülür. Özellikle, default
kullandığınızda veya herhangi struct
türde bir dizi oluşturduğunuzda çalışmazlar.
17.0'da, alan başlatıcılar varsa ancak bildirilmiş bir oluşturucu yoksa, alan başlatıcılarını çalıştıracak şekilde bir parametresiz oluşturucu otomatik olarak üretilir. Ancak bu, oluşturucu bildiriminin eklenmesi veya kaldırılmasının parametresiz bir oluşturucunun sentezlenip sentezlenmesini etkileyebileceği ve sonuç olarak davranışını new()
değiştirebileceği anlamına geliyordu.
Sorunu gidermek için .NET SDK 6.0.200'de (VS 17.1) derleyici artık parametresiz bir oluşturucu sentezlememektedir.
struct
alan başlatıcıları içeriyor ve açık yapıcılara sahip değilse, derleyici bir hata verir.
struct
Bir alan başlatıcısı varsa, bir oluşturucu bildirmesi gerekir, aksi takdirde alan başlatıcıları hiçbir zaman yürütülemez.
Ayrıca, oluşturucu bir : this()
başlatıcıya sahip değilse, alan başlatıcıya sahip olmayan tüm alanların her struct
oluşturucuda atanması gerekir.
Örneğin:
struct S // error CS8983: A 'struct' with field initializers must include an explicitly declared constructor.
{
int X = 1;
int Y;
}
Geçici çözüm bir oluşturucu bildirmektir. Alanlar daha önce atanmamışsa, bu oluşturucu genellikle boş bir parametresiz oluşturucu olabilir.
struct S
{
int X = 1;
int Y;
public S() { Y = 0; } // ok
}
Biçim tanımlayıcıları süslü parantez içeremez
.NET SDK 6.0.200, Visual Studio 2022 sürüm 17.1 ile kullanıma sunulmuştur. İlişkili dizelerdeki biçim tanımlayıcıları küme ayracı ( {
veya }
) içeremez. Önceki sürümlerde {{
kaçış {
karakteri olarak yorumlandı ve }}
biçim tanımlayıcısında kaçış }
karakteri olarak yorumlandı. Şimdi biçim belirticisindeki ilk }
karakter ilişkilendirmeyi sonlandırır ve herhangi bir {
karakter bir hatadır.
Bu, interpolasyonlu dize işlemenin System.String.Format
işlemedeki tutarlılığı sağlar.
using System;
Console.WriteLine($"{{{12:X}}}");
//prints now: "{C}" - not "{X}}"
X
, büyük harf onaltılık biçimidir ve C
, 12'nin onaltılık değeridir.
Geçici çözüm, biçim dizesindeki ek ayraçları kaldırmaktır.
Bu değişiklik hakkında daha fazla bilgi edinmek için ilgili roslyn konusunu inceleyebilirsiniz.
Türler adlandırılamaz required
Visual Studio 2022 sürüm 17.3'te kullanıma sunulmuştur. C# 11'den başlayarak türler olarak adlandırılamaz required
. Derleyici, bu türdeki tüm adlarda bir hata bildirecektir. Bu sorunu geçici olarak çözmek için tür adı ve tüm kullanımların bir @
ile kaçışı yapılmalıdır:
class required {} // Error CS9029
class @required {} // No error
Artık required
özellikler ve alanlar için bir üye değiştirici olduğundan, bu yapıldı.
İlişkili csharplang sorununda bu değişiklik hakkında daha fazla bilgi edinebilirsiniz.
Roslyn breaking changes