csharplang/meetings/2015/LDM-2015-09-02.md
2018-01-25 13:11:49 -08:00

4 KiB

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 branches. 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!):

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.