Aracılığıyla paylaş


.NET 6.0.100 ile .NET 7.0.100 arasında Roslyn'deki uyumsuz değişiklikler

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 IAttributeOperationolduğ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.NumericIntPtrgösterdiği gibi) yerleşik işleçler nint ve nuint bu temel türler için geçerlidir. Bu, bu tür platformlarda IntPtrchecked 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:

  1. Bağlamı belirt unchecked
  2. 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:

  1. UIntPtr.Add(UIntPtr, int) Yöntemini kullanın:UIntPtr.Add(x, y)
  2. İ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:

  1. Adın dış kapsamdan gölgelenmesinden kaçınmak için tür parametresini veya parametresini yeniden adlandırın.
  2. 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:

  1. "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
    }
    
  2. 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:

  1. ref struct türünü bir struct veya class türüne değiştirin.
  2. <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 AsyncEnumeratoryö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:

  1. Dönüştürme gerekmemesi için parametre türünü değiştirin.
  2. Ö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:

  1. Dönüş türü olarak kullanın @var .
  2. 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:

  1. Alıcı türünü interpolasyonlu dize işleyicisinden kaldırın.
  2. 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 UnmanagedCallersOnlyiliş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 defaultnull 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.