Source Generators in C# 9 will allow compiler-extensions to inspect code and then inject additional source code at compile-time. This injected code is then incorporated into the very same assembly that was being compiled. In order to facilitate this capability, Microsoft is removing most of the restrictions on Partial Methods.
Partial methods were introduced in 2007 to VB and C# to extend the capabilities of source code generators. The basic idea is that a source code generator would output code that invokes partial methods. If the developer wants to modify the behavior of the generated code, then the developer can implement the partial method. Otherwise the partial method is erased, as are any invocations of said method.
With source generators, the story is reversed. The developer starts by defining which partial methods are designed. Then the source generator sees the partial methods and implements them using a combination of ambient and external information. For example, the source generator may combine the attributes on a partial method with a database’s schema to generate a method, completely with SQL, for a database call.
Currently, partial methods have several restrictions including:
- Partial method declarations must return void.
- Partial methods can have in or ref but not out parameters.
- Partial methods are implicitly private, and therefore they cannot be virtual.
Under the first Extending Partial Methods proposal, these restrictions would be removed. The reason for this change is explained in the proposal:
This would expand the set of generator scenarios that partial methods could participate in and hence link in nicely with our source generators feature. For example a regex could be defined using the following pattern:
[RegexGenerated("(dog|cat|fish)")] partial bool IsPetMatch(string input);
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.
This would create a second category of partial methods that can’t be erased, but aren’t restricted in what you can do with them. In order to distinguish between the two categories, there are two basic rules:
- If partial appears with an explicit accessibility modifier (public, private, etc.), then it must be implemented, may return void, and may have out parameters.
- If partial appears without an explicit accessibility modifier, then it can be erased, must return void, and may not have an out parameter.
In a purely technical sense, this new category of partial method is really an abstract method because it must be implemented. But since it isn’t necessarily virtual, Microsoft decided that repurposing the abstract keyword would be too confusing.
Other class members such as partial properties, partial constructors, and partial operators are under consideration for C# 10. But as they are not strictly necessary for expanding the capabilities of source generators, they don’t want to introduce additional feature creep into C# 9.