Language Feature Proposals #1537
Replies: 16 comments
-
Most of these are championed proposals under development, with the exception of 1 and 2. |
Beta Was this translation helpful? Give feedback.
-
2 sounds a lot like inferred return types, which was rejected. |
Beta Was this translation helpful? Give feedback.
-
Beta Was this translation helpful? Give feedback.
-
@MgSam be nice. 😉 |
Beta Was this translation helpful? Give feedback.
-
A hint for next time - usual practice is to keep each issue to a single idea so that the discussion stays focused. This also makes it clearer which ideas are widely supported, and which are not. |
Beta Was this translation helpful? Give feedback.
-
@MgSam, @rlreis90, However, the alternative approach, of replacing private SomeType<SomeOtherType<IDictionary<string, ThirdType>, int, string>, ForthType>
_foo =
new SomeType<SomeOtherType<IDictionary<string, ThirdType>, int, string>, ForthType>(); with: private SomeType<SomeOtherType<IDictionary<string, ThirdType>, int, string>, ForthType>
_foo = new(); has been proposed in issue #100. 3. General purpose readonly and 5. switch expression 6. async foreach |
Beta Was this translation helpful? Give feedback.
-
It's not that async void M() // hm, why does this neeed to be async? there's no awaits inside
{
async foreach (var x in blah) // oh wait, they're hidden inside here!
{
Console.WriteLine(x);
}
} or void M()
{
async foreach (var x in blah) // error? but I marked this as async!
{
Console.WriteLine(x);
}
} While I agree that the
Have you also seen this year's build demo? https://www.youtube.com/watch?v=QZ0rWLaMZeI |
Beta Was this translation helpful? Give feedback.
-
@DavidArno Searching in the repo shows me a list of proposals, design notes, and issue suggestions related to my search. Do you have a better way of searching a repo for relevant content? If the poster had searched for almost any of the things he proposed he would have seen all the relevant information without having to open this issue. Try searching readonly local, for example. Getting tons of duplicate issue suggestions doesn't do favors for anyone. It adds a lot of noise, causes the same discussions to be repeated over and over, and makes this issue list even more irrelevant than it already is to the design team. Of course, it would be a lot better if MS would actually hire someone to take care of this repo, mark duplicates, and put a default template in for issue suggestions that encourages searching and careful thought before posting new issues, but I think that's about as likely as winning the lottery at this point. |
Beta Was this translation helpful? Give feedback.
-
First and foremost, thanks everyone for the valuable feedback and in-depth analysis! This is beyond what I had expected. Let me again reiterate my apologies for duplicate proposals. As you can surmise, I haven't looked too deeply into the repository. Just please don't get worked up over it. I'd like to respond to a few points here. @DavidArno @DavidArno & @Neme12 The reason why I said "async scope" instead of "async function" is because C# is not a functional language and does not care for purity. Many async methods are "void-returning" (Task type) and use statements, mutable variables, etc. In other words, rather than functions we are talking about code blocks; a delimited code block with it's own local variables, which I familiarly dubbed "a scope". I see @Neme12's point that it overloads the Thanks again. |
Beta Was this translation helpful? Give feedback.
-
Complexity in inference. What is public class Foo {
var X { get => this.Y; }
var Y { get => this.X; }
} That issue can crop up in a lot of other significantly more subtle ways. There was a thread about this recently here: #1484 In my opinion, the shape of the type (its fields and method signatures) should always be explicit. Having that shape depend entirely on an implementation can result in a domino effect where a minor change can result in a flurry of unintentional breaking changes. |
Beta Was this translation helpful? Give feedback.
-
@HaloFour That being said, in defense of item 2, we can deal with it by limiting the scope of the feature to only members without mutually recursive definitions. This is less ambitious, but still very much useful. I'm sure it's possible to do even better, but this is a solid first step. Thanks! |
Beta Was this translation helpful? Give feedback.
-
The same problems still arise. Those fields can be public and still rely on other inferred fields: public class Foo {
public static var A = Bar.A;
}
public class Bar {
public static var B = Foo.A;
} Rather than inferring the type of the field the team is looking into decreasing verbosity here by allowing for inference of the type in public class Foo {
public static Dictionary<string, int> dict = new(); // infers Dictionary<string, int>
}
The team has already pretty much weighed in that they would never consider implementing this. It's not worth the headache in engineering or the real impact to the user experience. |
Beta Was this translation helpful? Give feedback.
-
True, you can leverage class-level mutual recursion to do field-level stuff. That then reduces to the second case I've mentioned: to prevent implicitly typed fields to have recursive definitions. I'm fairly confident that this is possible as functional languages do even more than this. Scala in particular comes to mind. The new expression is nice, however it's too limiting. Often we don't want to say the name of the type at all. In my original example, a method can return whatever it wants and have that be the type of the field. Another use case is assigning a constant to a field, like a string. I'd rather avoid having to type the name of something so obvious, just like we can with local variables. And obviously you could make a literal as complicated as you want, by having any kind of tuple, array literal, etc. Even a new expression follows the same logic. As far as implementation goes, the logic should probably be close to lambda closures which generate classes from captured var locals--minus the fact that var locals don't have to worry about the crucial mutual recursion. |
Beta Was this translation helpful? Give feedback.
-
It's certainly possible, it's just not considered to be worth the effort or added complexity. It's somewhat rare for the C# team to outright close an issue here. Most kind of languish in the backlog. The fact that they closed that similar issue with a fairly absolute, "we are never going to do this," effectively closes the door on discussion around such inference in the C# compiler for the foreseeable future. |
Beta Was this translation helpful? Give feedback.
-
Unfortunately, the implementation would be vastly more complex for types/members. To the point that it would cost far too much and break so much of the designs we leverage in Roslyn for important purposes like performance. This is a case where the LDM has worked closely with the compiler devs and decided this just isn't feasible, and the benefit isn't work the exceptionally high price that would have to be paid. As such, other proposals (like target-typed-new) exist to somewhat ameliorate the pain here, but in a way that is felt to be much less constly to actually implement. |
Beta Was this translation helpful? Give feedback.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
-
Hi, I have a few language feature proposals. I apologize if they're duplicates or if this is not the appropriate place/format.
1.
var
fieldsFor a class declaration such as:
class Example { MyReallyLongTypeExpressionHere V = GetInstance(); }
It'd be nice if the type could be omitted:
class Example { var V = GetInstance(); }
All of the member modifiers should work with this in a natural way.
2
var
membersExtending the concept of 1, we can consider "var members" in general.
A "var property" Is probably the most straightforward case:
Immutable:
class Example { var V => 0; }
class Example { var V { get; } = 0; }
class Example { var V { get => 0; } }
Mutable:
class Example { var V { get; set; } = 0; }
class Example { var _V = 0; var V { get => _V; set => _V = value } }
We could also think of "var method"s, though I assume this would be more controversial:
class Example { var V() => 0; }
3. General purpose
readonly
Read-only class-level variables (fields) exist in C#. It'd be nice if they worked with all other kinds of variables as well. E.g:
Local variables:
Loop variables:
More generally, along the "variables as patterns" philosophy, we should think of
readonly var x
as a single object: a pattern.As such, any language feature that introduces variables should also accept "the
readonly
pattern". For example:foreach
(as above),using
andcase
statements,out
parameters, etc.4
val
keywordIntroduce a new keyword
val
with the same usage asvar
. It is nothing more than syntactic sugar forreadonly var
.In view of 1, this could also naturally work as
readonly var
fields.In view of 2, it should be an error to use
val
for properties with setters; it should only work with immutable properties.5.
switch
expressionIf the ultimate point of a switch statement is to map an input to a value, it'd be nice if the language allowed for a single, in-line expression to do it.
If we wanted to do it today, we'd have to do something like this:
It is cumbersome to write this. We have to keep track of state (
value
variable) manually and deal with a lot of noise -- put in the extra spacing, line breaks,break
statements, etc. Refactoring the switch statement out into a separate method with a series ofreturn
statements is better, but not fundamentally so -- it also requires non-locality of code.We can solve this with a
switch
expression which short-hands and eliminates this boiler plate.This is very much in line with functional programming and where pattern matching efforts in C# are going towards. Perhaps the team already has something of the sort in their sights.
We could talk about using expressions as well, but this is clearly the biggest use case.
6.
async foreach
This isn't as much a feature request as a small comment on a feature I've seen being talked about inBuild 2017.
I think it'd be nicer to have:
async foreach (var x in ...)
Instead of:
foreach await (var x in ...)
Because:
In any case, that's all for now. If anything, I hope this is good food for thought. Thank you!
Cheers!
Beta Was this translation helpful? Give feedback.
All reactions