102 lines
4 KiB
Markdown
102 lines
4 KiB
Markdown
|
C# Design Notes Sep 2 2015
|
||
|
==========================
|
||
|
|
||
|
Discussion for these notes can be found at https://github.com/dotnet/roslyn/issues/5234.
|
||
|
|
||
|
Quote of the day: Are you pulling the curtain away from my magic retort?
|
||
|
|
||
|
Agenda
|
||
|
------
|
||
|
|
||
|
1. Extending nameof
|
||
|
2. What do branches mean
|
||
|
3. Supersedes
|
||
|
|
||
|
|
||
|
Extending nameof
|
||
|
================
|
||
|
|
||
|
Should we allow empty type argument lists? When we first designed nameof the idea was to allow the same operands as typeof. During design we took it more in the direction of expressions, which seemed more useful.
|
||
|
|
||
|
However, it leaves a nuisance of providing type arguments that don't really provide any value.
|
||
|
|
||
|
One problem with this approach is what to do about situations like `MyList<>.First.P` where `First`'s type is the type parameter of `MyList`.
|
||
|
|
||
|
We would think of `MyList<>` as having a type argument that has no members at all - not even the ones from object. Thus, if you dot on it, you get an error.
|
||
|
|
||
|
More simply, just allow what's in typeof, followed by one member access. Make sure that, like in typeof, type arguments are either given everywhere or nowhere.
|
||
|
|
||
|
For inherited members/nested types, we should do the same as typeof does.
|
||
|
|
||
|
We don't expect this to upset analyzers much. We would make sure that the unbound types do have members in the semantic model. *Those* members just don't have members. Thus `MyList<>.First` is fine, but `MyList<>.First.P` is not.
|
||
|
|
||
|
We like this.
|
||
|
|
||
|
What do branches mean
|
||
|
=====================
|
||
|
|
||
|
As prototypes start to come online, we need to decide how we use our pbranches. The Future branch is for when things are at prototype level for the whole experience - including IDE. Features will be guarded by a feature flag until it's the confident plan of record to ship the feature in its current form.
|
||
|
|
||
|
We are working on enabling VSIXes to change the language model in the IDE without the need for customers to install over VS. Hopefully this capability will be available in an update to VS in a not too distant future. Once that is in place, we can ship prototypes that run without risk to customers' VS installation.
|
||
|
|
||
|
|
||
|
Supersedes
|
||
|
==========
|
||
|
|
||
|
For metaprogramming, like Javas annotation processing tool (APT), we would like to facilitate generating additional code from existing code (e.g. based on attributes or patterns). Roslyn now provides an excellent stack for that.
|
||
|
|
||
|
As a language C# is already better suited for this than Java because of partial types and methods: they allow the merging of existing and generated code to be less convoluted.
|
||
|
|
||
|
However we can do even better. We can allow omitting `partial` on one of the parts, so the user written code doesn't need it. But more interestingly we can consider a `supersedes` feature (where the keyword `supersedes` may need to be replaced by something that people have less trouble spelling!):
|
||
|
|
||
|
``` c#
|
||
|
class C
|
||
|
{
|
||
|
public void M()
|
||
|
{
|
||
|
// do stuff
|
||
|
}
|
||
|
|
||
|
[INPC] public int X {
|
||
|
get { ... }
|
||
|
set { ... }
|
||
|
}
|
||
|
|
||
|
// generated
|
||
|
partial class C
|
||
|
{
|
||
|
public supersedes void M()
|
||
|
{
|
||
|
// do something
|
||
|
superseded(); // calls original method
|
||
|
// do more
|
||
|
}
|
||
|
|
||
|
public supersedes int X {
|
||
|
get { return superseded; }
|
||
|
set
|
||
|
{
|
||
|
superseded = value;
|
||
|
RaiseNPC(nameof(X));
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
```
|
||
|
|
||
|
The compiler would generate code to keep the original `M` and `X` under a mangled name, inlined or something.
|
||
|
|
||
|
Challenge: composing multiple rewriters: either we have an ordering rule, or we get errors. This is a challenging problem.
|
||
|
|
||
|
Another good question: Do you have just one generator phase, or keep going to a fix point. Java keeps going until no changes.
|
||
|
|
||
|
Is the generated code visible to the user? You should see it like generated code today, and the compiler would parse it again to guard from mistakes. That way, code could also be generated by t4 and other tools, as well as Roslyn.
|
||
|
|
||
|
Concern: we are adding a new concept. Would it be better to use existing concepts, like Java does?
|
||
|
|
||
|
Concern: efficiency. Forces binding, throws away first result and binds again against generated code.
|
||
|
|
||
|
This is very interesting and promising, but there are many juicy challenges ahead.
|
||
|
|
||
|
|
||
|
|
||
|
|