Aracılığıyla paylaş


Kısmi Yöntemleri Genişletme

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, dil tasarım toplantısı (LDM) notlarındabelirtilir.

Özellik belirtimlerini C# dil standardına benimseme işlemi hakkında daha fazla bilgi edinmek içinbelirtimleri makalesinde bulabilirsiniz.

Şampiyon sorunu: https://github.com/dotnet/csharplang/issues/3301

Özet

Bu teklif, C# dilindeki partial yöntemlerinin imzalarıyla ilgili tüm kısıtlamaları kaldırmayı amaçlar. Amaç, bu yöntemlerin kaynak oluşturucularla çalışabileceği senaryo kümesini genişletmek ve C# yöntemleri için daha genel bir bildirim formu olmaktır.

Ayrıca bkz. özgün kısmi yöntem belirtimi (§15.6.9).

Motivasyon

C# geliştiricilerin yöntemleri bildirimlere ve tanımlara/uygulamalara bölmesine yönelik sınırlı desteğe sahiptir.

partial class C
{
    // The declaration of C.M
    partial void M(string message);
}

partial class C
{
    // The definition of C.M
    partial void M(string message) => Console.WriteLine(message);
}

partial yöntemlerin davranışlarından biri, tanım olmadığında dilin partial yöntemine yapılan çağrıları silmesidir. Temelde koşulun false olarak değerlendirildiği bir [Conditional] yöntemi çağrısı gibi davranır.

partial class D
{
    partial void M(string message);

    void Example()
    {
        M(GetIt()); // Call to M and GetIt erased at compile time
    }

    string GetIt() => "Hello World";
}

Bu özelliğin özgün motivasyonu, tasarımcı tarafından oluşturulan kod biçiminde kaynak oluşturmaydı. Kullanıcılar, oluşturulan kodun bazı yönlerini bağlamak istediklerinden, oluşturulan kodu sürekli düzenliyorlardı. Bileşenler başlatıldıktan sonra, özellikle Windows Forms başlatma sürecinin en önemli bölümleri.

Tasarımcının kodu yeniden oluşturmasına neden olan herhangi bir eylem kullanıcı düzenlemesinin silinmesine neden olabileceğinden oluşturulan kodu düzenlemek hataya neden oldu. partial yöntemi, tasarımcıların kancaları partial yöntemler biçiminde yaymalarına olanak sağladığından bu gerilimi azaltmıştı.

Tasarımcılar partial void OnComponentInit() gibi kancalar yayabilir ve geliştiriciler bunlar için bildirim tanımlayabilir veya tanımlamayabilir. Her iki durumda da oluşturulan kod derlenecekti ve işlemle ilgilenen geliştiriciler gerektiğinde bağlanabiliyordu.

Bu, kısmi yöntemlerin çeşitli kısıtlamaları olduğu anlamına gelir:

  1. Dönüş türü void olmalıdır.
  2. out parametreleri bulunamaz.
  3. Herhangi bir şekilde erişilebilir değil (örtük olarak private).

Çağrı sitesi silindiğinde dilin kod yayabilmesi gerektiğinden bu kısıtlamalar vardır. Silinebilecekleri için private, derleme meta verilerinde üyenin maruz kalamayacağı tek erişilebilirliktir. Bu kısıtlamalar, partial yöntemlerinin uygulanabileceği senaryo kümesini sınırlamaya da hizmet eder.

Buradaki teklif, partial yöntemleriyle ilgili mevcut kısıtlamaların tümünü kaldırmaktır. Temelde out parametrelerine, geçersiz olmayan dönüş türlerine veya herhangi bir erişilebilirlik türüne sahip olmalarına izin verin. Bu tür partial bildirimleri, bir tanımın mevcut olması gerektiği gereksinimini ekler. Bu, dilin arama sitelerini silmenin etkisini göz önünde bulundurması gerekmediği anlamına gelir.

Bu, partial yöntemlerin katılabileceği oluşturucu senaryoları kümesini genişletir ve bu nedenle kaynak oluşturucular özelliğimizle güzel bir şekilde bağlantı kurar. Örneğin, bir regex aşağıdaki desen kullanılarak tanımlanabilir:

[RegexGenerated("(dog|cat|fish)")]
partial bool IsPetMatch(string input);

Bu, hem geliştiriciye oluşturucuları seçmenin basit bir bildirimli yolunu sunar hem de oluşturuculara, oluşturulan çıkışlarını yönlendirmek için kaynak kodunda bakılması gereken çok kolay bir bildirim kümesi verir.

Bunu, bir oluşturucunun aşağıdaki kod parçacığını bağlama zorluğuyla karşılaştırın.

var regex = new RegularExpression("(dog|cat|fish)");
if (regex.IsMatch(someInput))
{

}

Derleyicinin oluşturucuların kod bağlamayı değiştirmesine izin vermediği göz önünde bulundurulduğunda, bu düzen oluşturucular için neredeyse imkansız olacaktır. IsMatch uygulamasında yansımaya başvurmaları veya kullanıcıların çağrı noktalarını yeni bir yöntemle değiştirmelerini + regex'i, dize sabitini bir bağımsız değişken olarak geçecek şekilde yeniden düzenlemelerini istemeleri gerekir. Oldukça dağınık.

Ayrıntılı Tasarım

Dil, partial yöntemlerin açık bir erişilebilirlik değiştiricisi ile açıklanmasına izin vermek için değişecek. Bu, private, publicvb. olarak etiketlenebileceği anlamına gelir.

bir partial yönteminde açık bir erişilebilirlik değiştiricisi olduğunda, dil, erişilebilirlik privateolsa bile bildirimin eşleşen bir tanımı olmasını gerektirir:

partial class C
{
    // Okay because no definition is required here
    partial void M1();

    // Okay because M2 has a definition
    private partial void M2();

    // Error: partial method M3 must have a definition
    private partial void M3();
}

partial class C
{
    private partial void M2() { }
}

Ayrıca dil, açık erişilebilirliği olan bir partial yönteminde nelerin görüntülenebileceğine ilişkin tüm kısıtlamaları kaldırır. Bu tür bildirimler geçersiz olmayan dönüş türleri, out parametreleri, extern değiştirici vb. içerebilir... Bu imzalar C# dilinin tüm ifadelerine sahip olacaktır.

partial class D
{
    // Okay
    internal partial bool TryParse(string s, out int i); 
}

partial class D
{
    internal partial bool TryParse(string s, out int i) { ... }
}

Bu açıkça partial yöntemlerin overrides ve interface uygulamalarına katılmasını sağlar:

interface IStudent
{
    string GetName();
}

partial class C : IStudent
{
    public virtual partial string GetName(); 
}

partial class C
{
    public virtual partial string GetName() => "Jarde";
}

Derleyici, bir partial metodu yasadışı bir öğe içerdiğinde yaydığı hatayı, temelde şunu belirtmek üzere değiştirecektir:

Açık erişilebilirliği olmayan bir ref yönteminde partial kullanılamaz

Bu, bu özelliği kullanırken geliştiricileri doğru yönde yönlendirmeye yardımcı olur.

Kısıtlama -ları:

  • Açık erişilebilirliği olan partial bildirimlerinin bir tanımı olmalıdır
  • partial bildirimleri ve tanım imzaları tüm yöntem ve parametre değiştiricilerinde eşleşmelidir. Farklı olabilecek tek yönler parametre adları ve öznitelik listeleridir (bu yeni değil, partial yöntemlerin mevcut bir gereksinimidir).

Sorular

kısmi tüm üyelerde

Kaynak oluşturuculara daha kullanışlı hale getirdiğimiz partial'ı, tüm sınıf üyeleri üzerinde de çalışacak şekilde genişletmeli miyiz? Örneğin, partial oluşturucuları, işleçleri vb. bildirebilmemiz gerekir...

Çözünürlük Fikir mantıklıdır ancak bu noktada C# 9 takviminde gereksiz özellik yığılmasını önlemeye çalışıyoruz. Modern kaynak oluşturucularla çalışacak şekilde özelliği genişletme sorununu acil olarak çözmek istiyorsunuz.

C# 10 sürümü için partial diğer üyeleri destekleyecek şekilde genişletilmesi dikkate alınacaktır. Bu uzantıyı dikkate almamız muhtemel görünüyor. Bu, etkin bir teklif olmaya devam eder, ancak henüz uygulanmamıştır.

Kısmi yerine soyut kullanma

Bu teklifin temel noktası, bir bildirimin karşılık gelen bir tanımı / uygulaması olmasını sağlamaktır. Geliştiriciyi bir uygulamaya sahip olmayı düşünmeye zorlayan bir dil anahtar sözcüğü olduğundan abstract kullanalım mı?

Çözüm Bu konuda sağlıklı bir tartışma vardı ama sonunda buna karşı karar verildi. Evet, gereksinimler tanıdıktır ancak kavramlar önemli ölçüde farklıdır. Geliştiricinin, aslında sanal yuvalar oluşturmadıkları halde, bunu yaptıklarına inanmasına kolayca yol açabilir.