83 lines
2.8 KiB
Markdown
83 lines
2.8 KiB
Markdown
|
# 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:
|
||
|
|
||
|
```c#
|
||
|
a[-5..-1] // Starts at length-5, excludes the last element
|
||
|
```
|
||
|
|
||
|
Proposal for start/count syntax:
|
||
|
|
||
|
``` c#
|
||
|
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.
|
||
|
|
||
|
``` c#
|
||
|
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.
|
||
|
|
||
|
``` c#
|
||
|
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.
|