Extender métodos parcialesExtending Partial Methods
ResumenSummary
Esta propuesta pretende quitar todas las restricciones en torno a las firmas de partial métodos en C#.This proposal aims to remove all restrictions around the signatures of partial methods in C#. El objetivo es expandir el conjunto de escenarios en los que estos métodos pueden trabajar con generadores de origen, así como un formulario de declaración más general para los métodos de C#.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.
Vea también la especificación de métodos parciales originales.See also the original partial methods specification.
MotivaciónMotivation
C# tiene compatibilidad limitada para que los desarrolladores dividan métodos en declaraciones y definiciones/implementaciones.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);
}
Un comportamiento de partial los métodos es que, cuando la definición está ausente, el lenguaje simplemente borrará las llamadas al partial método.One behavior of partial methods is that when the definition is absent then the language will simply erase any calls to the partial method. Esencialmente, se comporta como una llamada a un [Conditional] método en el que la condición se evaluó como false.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";
}
La motivación original para esta característica era la generación de código fuente en forma de código generado por el diseñador.The original motivation for this feature was source generation in the form of designer generated code. Los usuarios editaban constantemente el código generado porque querían enlazar algún aspecto del código generado.Users were constantly editing the generated code because they wanted to hook some aspect of the generated code. En particular, algunas partes del proceso de inicio de Windows Forms, después de que se inicializaran los componentes.Most notably parts of the Windows Forms startup process, after components were initialized.
La modificación del código generado era propensa a errores porque cualquier acción que hiciera que el diseñador regenerara el código haría que se borrara la edición del usuario.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. La partial característica de método facilitó esta tensión porque permitía a los diseñadores emitir enlaces en forma de partial métodos.The partial method feature eased this tension because it allowed designers to emit hooks in the form of partial methods.
Los diseñadores podrían emitir enlaces como partial void OnComponentInit() y los desarrolladores podían definir declaraciones para ellos o no definirlos.Designers could emit hooks like partial void OnComponentInit() and developers could define declarations for them or not define them. En cualquier caso, aunque el código generado se compile y los desarrolladores interesados en el proceso podrían enlazarse según sea necesario.In either case though the generated code would compile and developers who were interested in the process could hook in as needed.
Esto significa que los métodos parciales tienen varias restricciones:This does mean that partial methods have several restrictions:
- Debe tener un
voidtipo de valor devuelto.Must have avoidreturn type. - No puede tener
outparámetros.Cannot haveoutparameters. - No puede tener accesibilidad (implícitamente
private).Cannot have any accessibility (implicitlyprivate).
Estas restricciones existen porque el lenguaje debe ser capaz de emitir código cuando se borra el sitio de llamada.These restrictions exist because the language must be able to emit code when the call site is erased. Dado que se pueden borrar, private es la única accesibilidad posible porque el miembro no se puede exponer en los metadatos del ensamblado.Given they can be erased private is the only possible accessibility because the member can't be exposed in assembly metadata. Estas restricciones también sirven para limitar el conjunto de escenarios en los que partial se pueden aplicar los métodos.These restrictions also serve to limit the set of scenarios in which partial methods can be applied.
La propuesta aquí es quitar todas las restricciones existentes en torno a partial los métodos.The proposal here is to remove all of the existing restrictions around partial methods. En esencia, permita que tengan out tipos de valor devueltos que no sean void o cualquier tipo de accesibilidad.Essentially let them have out, non-void return types or any type of accessibility. Dichas partial declaraciones tendrían entonces el requisito agregado que debe existir una definición.Such partial declarations would then have the added requirement that a definition must exist. Esto significa que el lenguaje no tiene que tener en cuenta el impacto de borrar los sitios de llamada.That means the language does not have to consider the impact of erasing the call sites.
Esto expandiría el conjunto de escenarios de generador partial en los que podían participar los métodos y, por tanto, se vincularía perfectamente con nuestra característica de generadores de código fuente.This would expand the set of generator scenarios that partial methods could participate in and hence link in nicely with our source generators feature. Por ejemplo, una regex podría definirse con el siguiente patrón:For example a regex could be defined using the following pattern:
[RegexGenerated("(dog|cat|fish)")]
partial bool IsPetMatch(string input);
Esto ofrece al desarrollador una manera declarativa sencilla de optar a los generadores y proporcionar a los generadores un conjunto muy sencillo de declaraciones para buscar en el código fuente para impulsar la salida generada.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.
Compárelos con la dificultad de que un generador habría enlazado el siguiente fragmento de código.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))
{
}
Dado que el compilador no permite que los generadores modifiquen el enlace de código, este patrón sería bastante imposible para los generadores.Given that the compiler doesn't allow generators to modify code hooking up this pattern would be pretty much impossible for generators. Tendrían que recurrir a la reflexión en la IsMatch implementación o solicitar a los usuarios que cambien sus sitios de llamada a un nuevo método + refactorizar la expresión regular para pasar el literal de cadena como un argumento.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. Es bastante complicado.It's pretty messy.
Diseño detalladoDetailed Design
El idioma cambiará a permitir que partial los métodos se anoten con un modificador de accesibilidad explícito.The language will change to allow partial methods to be annotated with an explicit accessibility modifier. Esto significa que se pueden etiquetar como private , public , etc...This means they can be labeled as private, public, etc ...
Cuando un partial método tiene un modificador de accesibilidad explícito, aunque el lenguaje requiera que la declaración tenga una definición coincidente aunque la accesibilidad sea 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() { }
}
Además, el lenguaje quitará todas las restricciones sobre lo que puede aparecer en un partial método que tenga una accesibilidad explícita.Further the language will remove all restrictions on what can appear on a partial method which has an explicit accessibility. Estas declaraciones pueden contener tipos de valor devueltos no nulos, out parámetros, extern modificadores, etc. Estas firmas tendrán el expresividad completo del lenguaje C#.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) { }
}
Esto permite explícitamente partial que los métodos participen en las overrides interface implementaciones de y: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";
}
El compilador cambiará el error que emite cuando un partial método contiene un elemento no válido para decir esencialmente:The compiler will change the error it emits when a partial method contains an illegal element to essentially say:
No se puede usar
refen unpartialmétodo que carece de accesibilidad explícitaCannot userefon apartialmethod that lacks explicit accessibility
Esto le ayudará a los desarrolladores a apuntar a la dirección correcta al usar esta característica.This will help point developers in the right direction when using this feature.
Restricciones:Restrictions:
partiallas declaraciones con accesibilidad explícita deben tener una definiciónpartialdeclarations with explicit accessibility must have a definitionpartiallas declaraciones y las firmas de definición deben coincidir en todos los modificadores de método y parámetro.partialdeclarations and definition signatures must match on all method and parameter modifiers. Los únicos aspectos que pueden diferir son los nombres de parámetro y las listas de atributos (esto no es nuevo, sino un requisito existente departiallos métodos).The only aspects which can differ are parameter names and attribute lists (this is not new but rather an existing requirement ofpartialmethods).
PreguntasQuestions
parcial en todos los miembrospartial on all members
Dado que estamos expandiendo partial para ser más descriptivos para los generadores de código fuente, ¿también lo expandiremos para que funcione en todos los miembros de clase?Given that we're expanding partial to be more friendly to source generators should we also expand it to work on all class members? Por ejemplo, debería poder declarar partial constructores, operadores, etc.For example should we be able to declare partial constructors, operators, etc ...
Solución de La idea es un sonido, pero en este punto de la programación de C# 9 estamos intentando evitar el arrastre de características innecesario.Resolution The idea is sound but at this point in the C# 9 schedule we're trying to avoid unnecessary feature creep. Quiere resolver el problema inmediato de expandir la característica para trabajar con generadores de código fuente modernos.Want to solve the immediate problem of expanding the feature to work with modern source generators.
partialLa extensión para admitir otros miembros se considerará para la versión de C# 10.Extending partial to support other members will be considered for the C# 10 release. Parece probable que se considere esta extensión.Seems likely that we will consider this extension.
Usar Abstract en lugar de PartialUse abstract instead of partial
La quid de esta propuesta es esencialmente asegurarse de que una declaración tiene una definición/implementación correspondiente.The crux of this proposal is essentially ensuring that a declaration has a corresponding definition / implementation. Dado que deberíamos usar abstract , puesto que ya es una palabra clave del lenguaje que obliga al desarrollador a pensar en tener una implementación de?Given that should we use abstract since it's already a language keyword that forces the developer to think about having an implementation?
Solución de Hubo un debate en buen estado, pero finalmente se decidió.Resolution There was a healthy discussion about this but eventually it was decided against. Sí los requisitos son familiares, pero los conceptos son significativamente diferentes.Yes the requirements are familiar but the concepts are significantly different. Podría hacer que el desarrollador cree que estaba creando ranuras virtuales cuando no lo hacían.Could easily lead the developer to believe they were creating virtual slots when they were not doing so.