csharplang/meetings/2018/LDM-2018-01-31.md
2018-03-20 09:03:16 -07:00

2.8 KiB

C# Language Design for Jan 31, 2018

Warning: These are raw notes, and still need to be cleaned up. Read at your own peril!

Pattern-based fixed

If a type has a magic method of a certain name, which returns ref or ref readonly, you can fixed the type.

If you try to pin null or an empty array, you get a null pointer. It never throws.

For these new types, if it's a reference type we'll check first, and if it's null we'll return a null pointer. If the method wants to signal that there is nothing (e.g. an empty ImmutableArray struct), the proposal is to return a null ref. Those don't currently officially exist in the language, but you can manufacture one with unsafe code.

Extension methods

There are probably scenarios, such as adding the capability to an existing type based on an existing ref-returning member, or adding to certain constructions of a generic type.

But even because of consistency with how we've been doing pattern-based things for ages, we should allow it.

For string we want an instance method to win over the current way, but the current way to win over extension methods.

Ranges

Terminology: say "bounded/unbounded" instead of "open/closed". "Inclusive/exclusive" for whether the endpoint is included.

Negative indices

Proposal to have negative indices:

a[-5..-1] // Starts at length-5, excludes the last element

Proposal for start/count syntax:

a[5..+10] // Starts at 5, goes to 15 (exclusive)
a[-10..+3] // Starts at length-10, goes to length-7 (exclusive)

Is it important to support collections with nonzero (positive) start index?

Should the Bind method only take a length, not an index, for instance? Yes.

There might be the odd collection out there that's indexed, and doesn't start with 0. That's fine, but the feature is not for that. Those types wouldn't have methods that take ranges.

start/length notation

0..+-1

-5..+3 // -5..-2 -5..+5 // -5.. -5..+7 // throw

lexing/syntax

We've been liking : for this, but it is highly ambiguous with many aspects of the language: ternary operator, named arguments, format specifiers in interpolated strings.

a[3..+7]
a[3.+7]
a[3.:7] // Not ambiguous   object o = b ? 3..: 7.: 9 ; 
a[3..:7] // object o = b ? 3..: 7..: 9 ; find the range!
a[3:.7] // NO
a[3::7] // NO?
a[3:7] // NO
a[x:y] // NO

You don't need elision on either end for this. You only use it if you want to give a length. And if you want to start from the beginning you may just use ..x: length and end are the same.

3..-x
M(.:..)

Colons only: ambiguous, and looks symmetric. :: not as bad, only ambiguous with extern alias; realistic to semantically disambiguate. Plus: Looks like you are adding something, but clashes with unary +

.: is the plan of record.