gafter / roslyn Goto Github PK
View Code? Open in Web Editor NEWThis project forked from dotnet/roslyn
The .NET Compiler Platform ("Roslyn") provides open-source C# and Visual Basic compilers with rich code analysis APIs.
License: MIT License
This project forked from dotnet/roslyn
The .NET Compiler Platform ("Roslyn") provides open-source C# and Visual Basic compilers with rich code analysis APIs.
License: MIT License
From dotnet#40604 (comment)
I would like to consider adding the following forms to those that require a conversion to a type:
null
literal (except in specific contexts)That work doesn't belong on this branch, but is something we could do later after merging the target-typed conditional expression implementation to master.
It could likely simplify the compiler a lot because we have to handle these kinds of bound nodes specially in lots of different places in the code.
On 2016-02-10 the C# language design committee held a design review where we discussed our developing plan for records, and we got some feedback on suggested directions for the design. The design notes will be published separately. Enclosed is the outline of a design for records that illustrates the main points for one possible approach that is consistent with the design feedback. This is not intended to be a formal specification; we'll write that once we have agreement on the basic approach.
The basic approach here is that record declarations must be either sealed
or abstract
. Abstract record declarations have no state (by default), and do not implement object.Equals
or other equality methods. Abstract records can be seen as an optional feature of this approach; it would be possible for us to only do the sealed
version, with the possibility of expanding to support the abstract
version in the future if the need is seen to arise. Nevertheless, we'll start with a description of the syntax and semantics for abstract
records, as the sealed
record semantics will refer back to it when we describe the meaning of inheritance.
While you can think of a "record" as a sequence of named values, it should map to ordinary C# in a straightforward way. There should be as little "magic" as possible. If you write the "equivalent" C# for a record declaration, it should be indistinguishable to the language from the record declaration. Consequently when people "fall off the cliff" of what records provide by default (i.e. their use case is slightly different), they can simply resort to using ordinary class or struct declarations. It would be nice if most examples of "falling off the cliff" could be solved by providing only those members that need to be different from what the compiler would provide by default. For example, if you want one of the properties to be mutable instead of read-only, you just declare it yourself.
A few of the desired features
object.Equals
, object.GetHashCode
, and IEquality<T>
. These should be simple, reflexive, transitive, symmetric, etc.The benefit of this approach over other proposed approaches (specifically, those that place concrete data in an abstract record) is that there is no need for a canonical ordering of record members to be recorded in metadata as part of the meaning of the type. At the advice of the design review, we have done away with the concept of a record being defined as such a canonical ordering, and we define it very simply by translation into normal C# (with one small extension). The question of "how does the compiler know" how to match things up from one place to another does not arise in this formulation. Any such matching up is done purely locally. Still, a consequence of this expansion is that the record declaration construct can be thought of and can be used as if it is defined in terms of a canonical ordering of its members.
We will ignore IEquality<T>
and GetHashCode
for this.
An abstract record declaration defines an API that must be satisfied by classes that implement it. Taking our running example, given the declaration
public abstract Person(string FirstName, string LastName);
we would expand it into
public abstract class Person
{
public abstract string FirstName { get; }
public abstract string LastName { get; }
public abstract Person With(
string FirstName = this.FirstName,
string LastName = this.LastName);
public void GetValues(out string FirstName, out string LastName)
{
FirstName = this.FirstName;
LastName = this.LastName;
}
}
Not shown is the usual compiler-generated default constructor.
Here we see the proposed small feature in the parameter default values of the With
method: "caller receiver property". When the caller omits an argument for a parameter declared in this manner, the compiler generates, in the caller, an access to the property specified in the default value.
A sealed record declaration defines a concrete record type, which may extend a class and/or a set of interfaces. Given the declaration
public sealed class Student(int Id, string FirstName, string LastName, decimal Gpa) : Person;
we would expand it into
public sealed class Student
{
public int Id { get; } // 1
public override string FirstName { get; } // 2
public override string LastName { get; }
public decimal Gpa { get; }
public Student(int Id, string FirstName, string LastName, decimal Gpa) // 3
{
this.Id = Id;
this.FirstName = FirstName;
this.LastName = LastName;
this.Gpa = Gpa;
}
public override Person With(
string FirstName = this.FirstName,
string LastName = this.LastName) // 4
=> new Student(Id, FirstName, LastName, Gpa);
public new Student With(
int Id = this.Id,
string FirstName = this.FirstName,
string LastName = this.LastName,
decimal Gpa = this.Gpa) // 5
=> new Student(Id, FirstName, LastName, Gpa);
public void GetValues(
out int Id,
out string FirstName,
out string LastName,
out decimal Gpa) // 6
{
Id = this.Id;
FirstName = this.FirstName;
LastName = this.LastName;
Gpa = this.Gpa;
}
public override Equals(object that) // 7
{
Student other = that as Student;
return other != null &&
Equals(Gpa, other.Gpa) &&
Equals(FirstName, other.FirstName) &&
Equals(LastName, other.LastName) &&
Equals(Gpa, other.Gpa);
}
}
Now we have the question: how did the compiler know to produce each of these members in the form it did?
override
if a virtual or abstract property of the same name, type, and access is inherited.With
method is overridden if its return type is a supertype of the current type and every one of its parameters has a default value of the form this.X
where X is an overridden property according to (2). The implementation shall simply be an invocation of the "primary" constructor from (3).With
method similarly has a parameter for each record element, and invokes the primary constructor.GetValues
method similarly has an out
parameter for each record element, and initializes it from the corresponding generated property.Equals
method is the obvious and straightforward implementation.Note that there are no hard problems here. The mapping from the record declaration to the generated code is straightforward. The most complex mapping is for the implementation of an inherited With
method (4).
The only disadvantages arise in the presence of abstract records:
My first preference would be to support only the concrete (sealed) version of record declarations. But if we do intend to support abstract record declarations, I don't think there is a mapping as simple to understand as this one.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.