Kısmi yöntemleri genişletmeExtending Partial Methods

ÖzetSummary

Bu teklif, partial C# ' deki yöntemlerin imzaları etrafında tüm kısıtlamaları kaldırmak için amaçlar.This proposal aims to remove all restrictions around the signatures of partial methods in C#. Amaç, bu yöntemlerin kaynak oluşturucularla ve C# yöntemleri için daha genel bir bildirim formu olarak çalıştığı senaryolar kümesini genişletmektir.The goal being to expand the set of scenarios in which these methods can work with source generators as well as being a more general declaration form for C# methods.

Ayrıca bkz. özgün kısmi Yöntemler belirtimi.See also the original partial methods specification.

MotivasyonMotivation

C#, yöntemler için bildirimleri ve tanımları/uygulamaları bölmek için sınırlı destek içerir.C# has limited support for developers splitting methods into declarations and definitions / implementations.

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);
}

Yöntemlerin bir davranışı, partial tanım olmadığında dilin yalnızca yönteme yapılan çağrıları silecektir partial .One behavior of partial methods is that when the definition is absent then the language will simply erase any calls to the partial method. Temelde [Conditional] , koşulun yanlış olarak değerlendirilen bir yönteme çağrı gibi davranır.Essentially it behaves like a call to a [Conditional] method where the condition was evaluated to false.

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 özellik için özgün mosyon, tasarımcı tarafından oluşturulan kod biçiminde kaynak oluşturuliydi.The original motivation for this feature was source generation in the form of designer generated code. Oluşturulan kodun bazı yönlerini aşmaları gerektiğinden, kullanıcılar üretilen kodu sürekli düzenledi.Users were constantly editing the generated code because they wanted to hook some aspect of the generated code. Bileşen başlatıldıktan sonra Windows Forms başlangıç sürecinin çoğu bölümü.Most notably parts of the Windows Forms startup process, after components were initialized.

Tasarımcı 'nın kodu yeniden üretmesine neden olan herhangi bir eylem, Kullanıcı düzenlemenin silinmesine neden olacağından, oluşturulan kodu düzenlemek hataya açıktır.Editing the generated code was error prone because any action which caused the designer to regenerate the code would cause the user edit to be erased. partialYöntem özelliği, tasarımcılarının Yöntemler biçiminde kanca yaymaları izin verdiği için bu geriye sahiptir partial .The partial method feature eased this tension because it allowed designers to emit hooks in the form of partial methods.

Tasarımcılar benzer kancalar yayabilir partial void OnComponentInit() ve geliştiriciler onlar için bildirim tanımlayabilir veya tanımlamaz.Designers could emit hooks like partial void OnComponentInit() and developers could define declarations for them or not define them. Her iki durumda da, üretilen kodun derlenmesi ve işlemle ilgilenen geliştiriciler gerektiği gibi ilerleyebilse de.In either case though the generated code would compile and developers who were interested in the process could hook in as needed.

Bu, kısmi yöntemlerin çeşitli kısıtlamalara sahip olduğu anlamına gelir:This does mean that partial methods have several restrictions:

  1. Bir void dönüş türüne sahip olmalıdır.Must have a void return type.
  2. Parametrelere sahip olamaz out .Cannot have out parameters.
  3. Herhangi bir erişilebilirliği (örtük olarak private ) içeremez.Cannot have any accessibility (implicitly private).

Bu kısıtlamalar, dilin çağrı sitesi silindiklerinde kod yayabileceği için vardır.These restrictions exist because the language must be able to emit code when the call site is erased. privateÜye derleme meta verilerinde sunulamadığından, bu kişiler yalnızca olası erişilebilirlik olabilir.Given they can be erased private is the only possible accessibility because the member can't be exposed in assembly metadata. Bu kısıtlamalar Ayrıca yöntemlerin uygulanabileceğini belirleyen senaryolar kümesini sınırlandırmaya de olanak sağlar partial .These restrictions also serve to limit the set of scenarios in which partial methods can be applied.

Buradaki teklif, yöntemlerin çevresindeki mevcut kısıtlamaların tümünü kaldırmak için geçerlidir partial .The proposal here is to remove all of the existing restrictions around partial methods. Temelde out , void olmayan dönüş türlerine veya herhangi bir erişilebilirlik türüne sahip olmalarını sağlar.Essentially let them have out, non-void return types or any type of accessibility. Bu tür partial Bildirimler daha sonra bir tanımın mevcut olması gereken ek gereksinime sahip olur.Such partial declarations would then have the added requirement that a definition must exist. Bu, dilin çağrı sitelerini silme etkisini göz önünde bulundurmanız gereken anlamına gelir.That means the language does not have to consider the impact of erasing the call sites.

Bu, yöntemlerin katılabilen üretici senaryoları kümesini genişlettikten partial sonra kaynak oluşturanlar özelliğimize göre daha fazla bağlantı sağlayabilir.This would expand the set of generator scenarios that partial methods could participate in and hence link in nicely with our source generators feature. Örneğin, bir Regex aşağıdaki model kullanılarak tanımlanabilir:For example a regex could be defined using the following pattern:

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

Bu, hem geliştiriciye, hem de geliştiricilerin, kaynak kodda oluşturulan çıktıları sağlamak üzere kolay bir bildirim kümesi sunan basit bir bildirim sağlar.This gives both the developer a simple declarative way of opting into generators as well as giving generators a very easy set of declarations to look through in the source code to drive their generated output.

Bu sorunu, bir oluşturucunun aşağıdaki kod parçacığını birleştirme zorluğu ile karşılaştırın.Compare that with the difficulty that a generator would have hooking up the following snippet of code.

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

}

Derleyici, bu düzenin kodun takılme kodunu değiştirmesine izin vermediğinden, oluşturucular için oldukça olanaksızdır.Given that the compiler doesn't allow generators to modify code hooking up this pattern would be pretty much impossible for generators. Uygulamada yansıma oluşturmak IsMatch veya kullanıcılardan kendi çağrı sitelerini yeni bir yönteme değiştirmesini isteyen bir bağımsız değişken olarak dize sabit değerini bir bağımsız değişken olarak geçirmek için, Regex yeniden düzenleme yapması gerekir.They would need to resort to reflection in the IsMatch implementation, or asking users to change their call sites to a new method + refactor the regex to pass the string literal as an argument. Bu, oldukça önemlidir.It's pretty messy.

Ayrıntılı tasarımDetailed Design

partialAçık erişilebilirlik değiştiricisiyle yöntemlere açıklama eklenmesine izin vermek için dil değişecektir.The language will change to allow partial methods to be annotated with an explicit accessibility modifier. Bu,, vb. olarak etiketlenebilir anlamına gelir private public .This means they can be labeled as private, public, etc ...

Bir partial Yöntem açık bir erişilebilirlik değiştiricisine sahip olsa da, bu dil, erişilebilirlik şu olduğunda bile bildirimin eşleşen bir tanıma sahip olmasını gerektirir private :When a partial method has an explicit accessibility modifier though the language will require that the declaration has a matching definition even when the accessibility is private:

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() { }
}

Daha fazla dil, açık erişilebilirliği olan bir yöntemde görünebilecekleri tüm kısıtlamaları kaldırır partial .Further the language will remove all restrictions on what can appear on a partial method which has an explicit accessibility. Bu tür bildirimler void olmayan dönüş türleri, out Parametreler, extern değiştirici, vb. içerebilir. Bu imzalar C# dilinin tam ifade eder.Such declarations can contain non-void return types, out parameters, extern modifier, etc ... These signatures will have the full expressivity of the C# language.

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 ve uygulamalarına katılmasına izin overrides verir interface :This explicitly allows for partial methods to participate in overrides and interface implementations:

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 Yöntem temel olarak geçersiz bir öğe içerdiğinde gösterdiği hatayı değiştirecek:The compiler will change the error it emits when a partial method contains an illegal element to essentially say:

ref partial Açık erişilebilirliği olmayan bir yöntemde kullanılamazCannot use ref on a partial method that lacks explicit accessibility

Bu, geliştiricilerin bu özelliği kullanırken doğru yönde işaret etmelerine yardımcı olur.This will help point developers in the right direction when using this feature.

LarındanRestrictions:

  • partial Açık erişilebilirliği olan bildirimler bir tanıma sahip olmalıdırpartial declarations with explicit accessibility must have a definition
  • partial bildirimlerin ve tanım imzalarının tüm yöntem ve parametre değiştiricilerinde eşleşmesi gerekir.partial declarations and definition signatures must match on all method and parameter modifiers. Farklı olabilecek tek noktalar parametre adları ve öznitelik listeleridir (Bu yeni bir yöntem, ancak mevcut yöntemlerin bir gereksinimini yerine partial ).The only aspects which can differ are parameter names and attribute lists (this is not new but rather an existing requirement of partial methods).

SorularQuestions

Tüm üyelerde kısmipartial on all members

partialKaynak oluşturanlar için daha kolay olacak şekilde genişlettiğimiz için, aynı zamanda tüm sınıf üyelerinde çalışacak şekilde genişletireceğiz.Given that we're expanding partial to be more friendly to source generators should we also expand it to work on all class members? Örneğin partial , oluşturucular, işleçler vb. bildirebilmelidir.For example should we be able to declare partial constructors, operators, etc ...

Çözüm Fikir, ancak C# 9 zamanlamasında bu noktada gereksiz Özellik yayılmasını önlemek için çalışıyoruz.Resolution The idea is sound but at this point in the C# 9 schedule we're trying to avoid unnecessary feature creep. Özelliği, modern kaynak oluşturucularla çalışmak üzere genişletmenin hemen sorununu çözmek ister.Want to solve the immediate problem of expanding the feature to work with modern source generators.

partialDiğer üyeleri desteklemek için genişletme, C# 10 sürümü için göz önünde bulundurulacaktır.Extending partial to support other members will be considered for the C# 10 release. Büyük olasılıkla bu uzantıyı kabul edeceğiz.Seems likely that we will consider this extension.

Kısmi yerine soyut kullanınUse abstract instead of partial

Bu teklifin Crux 'i temel olarak bir bildirimin karşılık gelen bir tanım/uygulama içerdiğinden emin olur.The crux of this proposal is essentially ensuring that a declaration has a corresponding definition / implementation. abstractGeliştirici uygulamayı bir uygulamayla karşılaşmayı düşünürken zaten bir dil anahtar sözcüğü olduğundan, bu, kullanıyoruz.Given that should we use abstract since it's already a language keyword that forces the developer to think about having an implementation?

Çözüm Bu konu hakkında sağlam bir tartışma vardı, ancak sonuç olarak kararlandı.Resolution There was a healthy discussion about this but eventually it was decided against. Evet, gereksinimler tanıdık, ancak kavramlar önemli ölçüde farklıdır.Yes the requirements are familiar but the concepts are significantly different. , Geliştiriciye bu şekilde sanal yuvalar oluşturduklarında, kolayca bir şekilde yol açabilir.Could easily lead the developer to believe they were creating virtual slots when they were not doing so.