C# 7 Work List of Features #2136

Open
MadsTorgersen opened this Issue Apr 21, 2015 · 440 comments

Projects

None yet
@MadsTorgersen
Contributor
MadsTorgersen commented Apr 21, 2015 edited

(revision circa April 26 2016, clarifying edit June 14, 2016)

This is a list of features are looking at for C# 7, roughly categorized according to our current level of interest and estimated plausibility.

Please don't infer anything about the final shape of C# 7 (or future versions). The list is a tracking mechanism for work, not a description of the outcome. We have a long way to go yet!

Each bucket is in no particular order. I'll try to think of a more systematic way of cross-referencing with proposals and notes, but wanted to get the list out there.

I'll keep the list updated as we look at more feature ideas and change our minds about the relative importance.

Strong interest

  • Local functions (Proposal: #259) [currently in future branch]
  • Tuples (Proposal: #347)
  • Pattern matching, part I (type patterns in switch statements and is-expressions) (subset of Proposal: #206 Pattern Matching)
  • Ref locals and ref returns (Proposal: #118)
  • replace/original (part of generators) (Proposals: #5292, #5561)

Some interest

  • Binary literals (Proposal: #215) [currently in future branch]
  • Digit separators (Proposal: #216) [currently in future branch]
  • out var (Proposal: #6183)
  • Async main (Proposal: #7476)
  • address of static method for unsafe interop code (Do we have a proposal?)

Non-language


See also Language Feature Status (compiler team)

@MadsTorgersen MadsTorgersen self-assigned this Apr 21, 2015
@MadsTorgersen MadsTorgersen added this to the C# 7 and VB 15 milestone Apr 21, 2015
@erik-kallen

What has happened to variable declaration expressions (which almost made it into C# 6) and the semicolon operator?

@khellang

Yeah. Declaration expressions was one feature I was really looking forward to in C# 6. I hope they're not dropped for good.

@SolalPirelli
  • Supersedes

What does that point mean? Searching for "supersedes" in the issues only returns this one. :)

@dsaf
dsaf commented Apr 21, 2015

Is there any possibility that it will be released before the next version of Visual Studio? Waiting for two years to get all those awesome features would make me sad (although I have no idea about the complexity of the work).

PS: TypeScript seems to have lots of minor versions released.

@stephentoub
Member

@MadsTorgersen, I updated the description with some more proposal #s.

We should probably separate out from "Safe fixed-size buffers" the ability to use custom types (rather than the small set of primitives allowed today) in fixed-size buffers. That's separate from being able to use fixed-size buffers in safe structs, but we lumped them together when discussing how we probably wouldn't get to "safe fixed-size buffers".

What about the Nothing / DoesNotReturn feature?

@stepanbenes

Deterministic disposal feature is mentioned both in "Some interest" bucket and "Probably never" bucket (as Destructible types). Having link to same proposal I suppose they both refer to the same thing.

@stephentoub
Member

@stepanbenes, I believe what Mads is trying to convey is that the specific solution called out in the proposal is something we don't intend to do as-is, but we would still like to do something to address the same problem area.

@HaloFour

The "Strong Interest" list is awesome. Pattern matching will be a huge addition to the language. I'm quite excited about async streams as well but I would hope that there is some room to consider IObservable<T> as well as a new IAsyncEnumerable<T>. I'd be happy to contribute towards that solution.

About static members in an interface, I believe that the CLR already permits that. Unless I'm misinterpreting what the feature entails. You also already have CLR support for enum and delegate generic constraints, but I could understand maybe wanting to lump that up with work to expose many more flavors of generic constraints.

@MgSam
MgSam commented Apr 21, 2015

Quite the list when you spell it all out!

I agree with nearly everything in the "Strong Interest" bucket. The "Some Interest" bucket has some good ones but also a few "meh" features listed, IMO, and is missing some good ones.

Off the top of my head:

@MgSam
MgSam commented Apr 21, 2015

Also- I'm surprised readonly locals is in the "Some Interest" bucket. From the comments in the discussions it seems like there's strong interest in this, the only minor point of contention is whether to use let or val. I think this feature is just as useful, if not more useful, than the proposed non-nullability analyzers.

@MovGP0
MovGP0 commented Apr 22, 2015

I guess the features that would reduce developer errors most are:

  • non-nullable reference types
    • var! dog = new Dog();
  • immutable values
    • let age = 26;
    • immutable int age = 26;
  • immutable types
    • public immutable sealed class Dog { ... }
  • contracts
    • [Requires(...)] [Ensures(...)]
    • requires ..., ensures ...
  • units (C# 8? syntax?)
@dsaf
dsaf commented Apr 22, 2015

@MovGP0 In my experience in enterprise web dev the predominant majority of errors are made outside of C# code - JavaScript, HTML, CSS, SQL. I wish Spartan would just support C# and some lighter XAML natively... So I guess it makes sense to focus on the features that improve language expressiveness instead.

@Eirenarch

Your strong interest list makes me very happy.

@paavohuhtala

@seanfreiburg How would that differ from the ??-operator?

@JoshVarty
Member

Any thoughts on #13 (Anonymous types that implement interfaces)?

Also, I think there would need to be a lot of thought given to declaration expressions before they should be "bucketed". The scoping issues from last time will need a lot of discussion. Personally, I still don't like any of the options there (especially the proposal to remove the shadowing restriction)

@MovGP0
MovGP0 commented Apr 23, 2015

@dsaf well, yes and no. you are probably right that in other languages, developers make even more errors. still, F# developers make even less errors than C# developers. so it makes sense to make C# more like F#.

besides, XAML/C# in the browser was tried with Silverlight, but sadly unsuccessful. I bet the best chances are to use C#/F# to JavaScript compilers with HTML in the frontend.

@amitsaini12345

I want To have the feature providing the runtime object defination will be changed. This will help of allowing the heavy objects of class. For e.g. if we do not need all the properties at a moment, we will use one rquired object of properties and no need to define separate classes and inheritance.

is it possible??.

If possible plz introduce such a feature. it will be great memory saving.

@weitzhandler

@dsaf #2136 (comment):

besides, XAML/C# in the browser was tried with Silverlight, but sadly unsuccessful. I bet the best chances are to use C#/F# to JavaScript compilers with HTML in the frontend.

Ditto! Unfortunately it doesn't look like MS is going to open their eyes about this any time soon.
With Apache Cordova and the like, this makes the whole even more attractive, having C# and XAML be the ultimate pair for Windows desktop, store, Android, OS X, iOS, and web.
Of all UI solutions XAML is the best. HTML-CSS-JS is a pain the ass, pardon my french.
There are many solutions about this out there, nothing free, nothing out-the-box.

@jsphadetula

What about support for auto generated object composition

@Eirenarch

Sad to see declaration expressions and especially params IEnumerable go. Is there anything that was dropped in the last couple of months and where can I read about it? I checked the status page - https://roslyn.codeplex.com/wikipage?title=Language%20Feature%20Status&referringTitle=Documentation but it seems like features that were dropped were removed from the table instead of marked as dropped.

@srgloureiro

Reference to constant parameters as in C++ would be a suggestion from me.

@GoEddie
GoEddie commented Apr 23, 2015

Hey Mads - what about:

#102

Any idea where it fits?

@Eirenarch

@GoEddie for practical purposes this is covered by the Tuple proposal

@mcintyre321

I favour anonymous return types over the tuple proposal. Seems like a small change to achieve the same effect.

Also strong interest for Declaration expressions.

@GoEddie
GoEddie commented Apr 23, 2015

@Eirenarch thanks! I have updated 102 to point to the tuple proposal

@jcdickinson

Shooting from the hip here.

Allow extension methods in non-static classes

Does allowing extension methods in interfaces make sense? Consider the current scenario with IEnumerable<T>, had interface extension methods been available the extension methods could have been placed in the interface saving marginally on namespace pollution (instead of the current situation with Enumerable). This would mean that interfaces would be one step closer to becoming mixins.

  • Implement as a native CLR feature - con: needs CLR support
  • Implement by automatically moving the methods into a compiler-generated class - con: bad language interopability
@iainholder

I'd be interested to know why INPC support is in the probably never bucket. Is that because it's
a) hard
b) easy but why build in support for something that already has a few well known patterns or
c) INPC will be irrelevant by the time C#7 comes out?

@HaloFour

CLR/IL allows static members in interfaces. Might be useful for defining
extension methods close to the extended interface or for virtual
extension methods assuming the CLR could be changed to add a vtable slot
that would default to that static method.

Still, removing the limitation that extension methods be defined on static
classes would be helpful in eliminating the need for additional cases to
support some API and I welcome it.
On Apr 23, 2015 8:03 AM, "Jonathan Dickinson" notifications@github.com
wrote:

Shooting from the hip here.

Allow extension methods in non-static classes

Does allowing extension methods in interfaces make sense? Consider the
current scenario with IEnumerable, had interface extension methods
been available the extension methods could have been placed in the
interface saving marginally on namespace pollution (instead of the current
situation with Enumerable). This would mean that interfaces would be one
step closer to becoming mixins.

  • Implement as a native CLR feature - con: needs CLR support
  • Implement by automatically moving the methods into a
    compiler-generated class - con: bad language interopability


Reply to this email directly or view it on GitHub
#2136 (comment).

@ufcpp
ufcpp commented Apr 23, 2015

@iainholder INPC is listed in #1677 as 'too specific; metaprogramming?'

@bencyoung

One thing that would be extremely beneficial for Linq performance would be IExactSizedEnumerable and IMaxSizedEnumerable or similar. Often you have chains of operations of Linq operations on a container and the fact that an exact result size is expected is lost. If the size can be preserved then the amount of allocation and copying that takes place in ToArray, ToList etc can be minimised.

Python does this using a property called length_hint https://www.python.org/dev/peps/pep-0424/

@jcdickinson

IExactSizedEnumerable = IReadOnlyCollection.

@BrandesEric

+1 for the Tuple proposal. Multiple return values is really the only remaining feature I really want. Given what I feel is the community's general distaste for Tuples, perhaps it would be worth calling the proposal "Multiple return types (Tuples)" or something :)

@weitzhandler

#2136 (comment)

I'd be interested to know why INPC support is in the probably never bucket.

I believe because it's too technology specific. There are no need for INPC in ASP.NET or console apps for example.
With the introduction of the nameof operator, INPC will become much nicer and safer anyway.

@jcdickinson

And building INPC into the compiler locks everyone into a specific implementation. I have personally written 3 different implementations of INPC, that approached INPC differently and needed to approach INPC differently. Metaprogramming is the correct way to completely solve the problem, especially in combination with compile-time attributes.

@bencyoung

IExactSizedEnumerable = IReadOnlyCollection is true, so perhaps my request should be changed to Select on an ICollection should return an IReadonlyCollection rather than IEnumerable. There are other cases where an approximate or maximum size is known where other interfaces may be useful

@Mechazawa

I strongly support adding binary literals. It would make a lot of my code less awkward looking when I'm doing things like Boolean algebra or using flags. I'm not that familiar with how the compiler handles things like base 16 literals but I don't expect that it would be much different from how they are implemented.

edit: A quick look at the source code of the Lexer reveals that it would be quite trivial to implement (somewhere around here?). Again I'm not that familiar with the compiler. I could attempt creating a proof of concept when it comes to implementing this.

@wesnerm
wesnerm commented Apr 23, 2015

Mads, there is one mistake. Static interface methods are already supported in the CLR; they are not CLS-compliant though, but potentially could be by changing the spec.

I recall that there was a .NET language that actually included this feature. I believe it is C++/CLI.

http://stackoverflow.com/questions/19496397/implementing-interface-with-static-methods-in-c-sharp

@wesnerm
wesnerm commented Apr 23, 2015

Proper tail calls is very easy to add and potentially enables a new programming style. The CLR already has support for this and languages like F# uses it. It makes an extremely elegant and natural implementation of backtracking possible, for example, without a stack! A backtracking algorithm needs a success continuation and a failure continuation.

@HaloFour

@wesnerm Well neither is uint but that hasn't stopped anybody. 😄

Indeed, I tested static members in interfaces in CIL and they work fine and PEVerify is happy about it. I remember them being mentioned in the Inside Microsoft .NET IL Assembler book published back in 2002.

@keilw
keilw commented Apr 23, 2015

@MovGP0 Good point, at least F# already support units and we're working on something similar for the Java platform, too ;-)

@rsmckinney

Type providers 👍

@Ultrahead

@MadsTorgersen: "Additional generic constraints" should also refer to #262 (which as stated above by @HaloFour already is supported by the CLR)

@garora
garora commented Apr 23, 2015

What about variable declaration ?

@mhomde
mhomde commented Apr 23, 2015

Hi guys, nice list! Nothing on pre, post and test blocks? All the features listed are really nice additions to the language, but I feel like one area that really could need some language integration is error checking and testing (nullability tracking is a great step in this direction as well) .

I think that's something that could have a real impact on the quality real-world projects which often have problems managing quality and finding bugs

Se suggestions in #106

@svick
Contributor
svick commented Apr 23, 2015

@bencyoung There is nothing that needs to change in C# for that. And the change in the
framework is already being worked on, see dotnet/corefx#1282.

@dotnetchris

PLEASE PLEASE everything in the small but useful list!

@wesnerm
wesnerm commented Apr 23, 2015

Since static interface methods are already supported by the CLR, default interface methods can be easily added to the C# language with retroactive support for older runtimes.

A class can map an interface method directly to a static interface method (with an explicit this parameter) or to a stub instance method that calls that static interface method directly. One design issue is whether default methods are public or private (only called explicitly through the interface).

@HaloFour

@wesnerm I don't think that's the case. Adding a new "default method" would still leave a blank spot in the vtable slot that older runtimes would not know to wire up to that static instance method. You could have newly compiled classes do that automagickally but not already compiled assemblies.

@Aaronontheweb

Default implementations on interfaces (#73) would be massively useful - Scala traits provide a great working model for this. Hope to see this in the CLR.

@horsdal
horsdal commented Apr 23, 2015

Good to see pattern matching (and friends) so high on the list. The would/will really be an enabling feature for a lot of nice stuff.

@Aaronontheweb

Immutable types #159 would also be amazing.

@JayBazuzi

I often wish for extension methods in nested private static classes, although "Allow extension methods in non-static classes" would cover most of that need.

@mariusschulz

If I had to pick a single feature that excites me most, it would without doubt be Algebraic data types. Very happy to see it on the Strong interest list!

@dotnetchris

@JayBazuzi we only wanted them in nested private classes because of the arbitrary requirement that they couldn't be in a nonstatic class

@RobertGBryan

What about a common sense and reasonably easy to implement feature to retrieve a key from a Dictionary, HashSet, SortedDictionary, or any other container class that uses keys?

Right now, only values can be retrieved from a Dictionary - not the key. Unless iterating through the dictionary with a foreach loop - which would be prohibitively expensive when doing a simple look up. It would be nice if a method could be provided that would return the key/value pair for a given key from a matching "key". The reason why it would be useful is because the Equals method does not necessarily mean that 2 objects are exactly equal - since the Equals method can and often does only use a subset of the fields of a class to make that determination. I have come across cases where it would have been quite helpful to access the stored key in the dictionary when my code found the item in the dictionary. There were other fields in the stored key that I needed to access that were not present in the key used to access the dictionary, so I had to use the suggested work around given in the link above.

@wesnerm
wesnerm commented Apr 24, 2015

@RobertGBryan, it's a simple thing to include the key with the value or to make the value a tuple. If there's a canonical name, it should be probably included with the value.

@RobertGBryan

@wesnerm, Sounds like you are suggesting using the work around specified in the link above. The drawback as pointed out by the original poster in that link is that it adds complexity as well as needlessly takes up more memory. How hard would it be to provide a method to return the key and value? Wouldn't this be a fairly simple task to implement?

@wesnerm
wesnerm commented Apr 24, 2015

@HaloFour,

"Adding a new "default method" would still leave a blank spot in the vtable slot that older runtimes would not know to wire up to that static instance method. You could have newly compiled classes do that automagickally but not already compiled assemblies."

No, there would be no blank slot. It's not a runtime feature, but a compiler feature.

In the IL, there would always be some method assigned to slot. In C# 7.0, the compiler would implement a private instance method that calls the static interface method. (Calls to static interface methods are actually supported by older versions of C#.)

.method private virtual void ClassInterfaceMethod()
{
    .override IInterface::InterfaceMethod
    ldarg.0
    call void IInterface::InterfaceStaticMethod(Interface)
    ret
}

InterfaceStaticMethod and InterfaceMethod might have the same name, since that is possible in IL.

An older compiler using a library with a default interface method would not know about it and would require the developer to always implement either a explicit or implicit interface implementation. A developer using the older compiler could recreate the same implementation as C# 7.0 manually.

void IInterface.ClassInterfaceMethod()
{
    IInterface.InterfaceStaticMethod(this);
}

Default implementations can be implemented with attributes on the static interface method, just like with extension methods or param arrays. C# 7.0 would recognize the default implementations automatically when a user-provided implementation is missing. With no performance loss, C# 7.0 would locate a static method of the same name taking the same arguments (including the this parameter) and checking for the presence of a DefaultInterfaceMethodAttribute on the static method.

@HaloFour

@RobertGBryan You should suggest that to the CoreFX Team. They consider possible API changes to the framework.

@thomaslevesque
Contributor

@RobertGBryan, that's a library issue, not a language issue. That won't be fixed by a new feature in the language.

@HaloFour

@wesnerm That would break all existing implementers of that interface that are compiled outside of that project. That defeats most of the purpose of "default methods" which is the ability to add new trivial methods to an existing interface without requiring recompilation of implementing classes.

@drothmaler

If you are going to implement Null safety in the Kotlin way, maybe you could check out a few of their other concepts too. I think especially the concepts of smart casts and delegated properties could be really useful...

String templates, first-class delegation, extension properties and
singleton objects are also nice.

BTW: I think delegated properties (maybe in combination with first-class delegation?) could also solve the INPC problem.

@Tomamais

Why not Metaprogramming? :'(

@lukebuehler

+1 Type providers! Please!

@SimonCropp

@MadsTorgersen can u elaborate on "compile time attributes"?

@SimonCropp

Enum and generic constraints please so i can delete this project https://github.com/Fody/ExtraConstraints

@chassq
chassq commented Apr 30, 2015

Not sure how this fits in but would like to see Enums made more useful. Something like java Enums. I cannot say how many times I would like to have a bit more information attached to the Enum (e.g. a description). Can be done with [Description] attribute today but just would be nice if Enums were more extensible. The other thing would be the capability to do more generic work with Enums. Hope this makes some sense.

@khellang

What happened to duck-/structural typing? I seem to recall it was mentioned in one of the design note issues... That would be really awesome. Or even a hack like Assembly Neutral Interfaces 😄

@eamodio
eamodio commented May 4, 2015

+1 for structural typing. That would be awesome. Spoilt by TypeScript.

@adamralph
Contributor

Excuse my ignorance, but what is INPC?

@mcintyre321

INotifyPropertyChanged - I guess it's talking about an automatic implementation a la ES6 Object.Observe

I personally would love this (especially recursive INPC) for doing object diffing of viewmodels and change tracking for reactive server side views and stuff.

@adamralph
Contributor

@mcintyre321 thanks. Never used it 😛

@TwoRedCells

I don't think #154 would require CLR support, but if it does I'd be interested how. When I designed it, I envisioned it as a compile-time language-only feature.

I can see how #129 would require run-time support.

@TwoRedCells

@khellang I think #154 could be considered Duck typing.

@TwoRedCells

@RobertGBryan in case you weren't aware, IDictionary, IDictionary<TKey,TValue>, HashTable, Dictionary<TKey,TValue> etc. all implement IEnumerable. Specifically, Dictionary<TKey,TValue> implements IEnumerable<KeyValuePair<TKey,TValue>> which I think is what you're looking for. It also has Keys and Values properties that you can use to iterate them separately, if desired.

@MpDzik
MpDzik commented May 10, 2015

+1 for Nullability tracking (Proposal: #227)

@orthoxerox

+1 for ref locals. When you have a very hot number-crunching loop, you have to resort to an array of structs to hold your data to improve data locality, and to shave off the final milliseconds you need to avoid copying the element you are processing into a local. This either means recalculating the offset again and again or extracting the loop body into a static method with a ref parameter. The latter option is the fastest, but can be confusing to those supporting the code.

@whoisj
whoisj commented May 11, 2015

Can I please add a new feature request, if this isn't the place to do so please tell me where the right place is.

Not sure what to call it, but basically I want the ability to pass a reference into a method and know that method will not take an additional reference. For example, if I allocate a large block of memory and I pass a reference to that allocation into a method, I would like to know that the method will not keep a reference to the memory thus preventing the GC from doing its job.

Effectively I'd like parameter operator which creates a contract with the call that the method will not take a reference to the parameter nor will it is pass the reference to another method which doesn't support the same contract.

A use-case could be something as simple as Encoder's .GetString method.

public string GetString(&byte[] bytes)

Where the & is used to signify that the reference cannot be held on to.

@HaloFour

@whoisj

Can I please add a new feature request, if this isn't the place to do so please tell me where the right place is.

You can create a new issue for the proposal. Then it will be tracked separately and can have its own dialog.

@whoisj
whoisj commented May 11, 2015

@HaloFour yay, thanks!

@ehouarn-perret

Any news about the constraints support for delegates and enums?
Here is a link to bring some memories back: http://blogs.msmvps.com/jonskeet/2009/09/10/generic-constraints-for-enums-and-delegates/

@dsaf
dsaf commented May 17, 2015

@ehouarn-perret Additional constraints are explicitly mentioned in the opening post itself: "Small but useful" and "Interesting but require CLR support" sections.

@HaloFour

To note, as mentioned on Jon Skeet's blog and on here and CodePlex numerous times, supporting delegates or enums as generic type constraints are both currently supported by the CLR, just not by C#. C# already recognizes and enforces said constraints if you reference another assembly that uses them.

Here are the two existing proposals for this:

#158 Proposal: Support System.Delegate as a generic constraint
#262 Proposal: support an enum constraint on generic type parameters

@ehouarn-perret

@HaloFour
@dsaf
Alright then, glad to know that those suggestions are still around and have been considered for C# 7 :-)

I'm already aware of what Jon Skeet has found (a long time ago, about 6-7 years ago).
And fully agreed as it has been already pointed out many times this is already supported by the CLR.
Sadly, C# still lacks its language counterpart.

Thanks about the links, that was exactly what I was looking for.

@Ultrahead

Would generic constraints for enum types require CLR support? Or is already supported by the CLR? (given that F# already has this feature)

El 22 jun. 2016, a las 9:14 a.m., Eyal Solnik notifications@github.com escribió:

@msedi I completely support the need for more support to generic constraints, currently it's very limited but besides this if C# allowed you to tweak every single bit like C++ does it wouldn't be C# anymore.

@HaloFour I read @gafter post about CLR changes #420 but it's quite old, I wonder when these changes will be implemented, if ever. :)


You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub, or mute the thread.

@HaloFour

@Ultrahead

F# fakes all of its additional constraints. Said members often either can't be expose outside of their defining assembly or they "collapse" down into non-generic version. For example:

type Foo = class
    static member Add (value1 : ^T when ^T : (static member (+) : ^T * ^T -> ^T), value2: ^T) =
        value1 + value2
end

Is effectively:

type Foo = class
    static member Add (value1 : int, value2: int) =
        value1 + value2
end

And even F# won't let you call that method with operands of other types.

Sometimes F# just doesn't enforce the constraint at all and calling the method from another language just results in a run time exception.

@msedi
msedi commented Jun 22, 2016

@eyalsk:

maybe they can add some C++ features in the context of unsafe

That would be completely OK for me.

@eyalsk
eyalsk commented Jun 22, 2016

@msedi You probably know that but I don't think it will ever happen at least not in the context of unsafe.

I really think that you should write a post or multiple ones about your problems and also provide solutions as a starting point for discussion, it's much better than discussing these issues in comments because comments are harder to track. :)

@FunctionalFirst

@HaloFour

F# fakes all of its additional constraints.

In what sense are they fake?

Said members often either can't be expose outside of their defining assembly or they "collapse" down into non-generic version.

That's not accurate. F# supports two kinds of type parameters, standard .NET generics (a la C#) and statically resolved type parameters (think C++ templates). The type params in your example function "collapse" because member constraints are statically resolved, which requires marking your function inline.

@HaloFour

@FunctionalFirst

"Fake" in the sense that they're not CLR constraints. They don't survive outside of the assembly and can't be used from other languages. This is unlike enum or delegate constraints which are supported by the CLR, just not by C#.

The inline modifier does indeed keep that method generic, but with no constraints. F# uses its own library to attempt to dynamically perform the addition based on the type of the operands, which will invariably be slower than IL add on a native numeric data type. It also offers no type safety.

@FunctionalFirst

@HaloFour

"Fake" in the sense that they're not CLR constraints.

I'm not sure why a compiler enforced constraint is fake, but a CLR constraint isn't. F# stores metadata about compile-time constraints, so they do survive beyond the defining assembly.

@HaloFour

@FunctionalFirst

I'm not sure why a compiler enforced constraint is fake, but a CLR constraint isn't.

Perhaps "fake" was a bad choice of words. It's not a CLR generic type constraint, which is what C# supports. It's a different beast altogether.

F# stores metadata about compile-time constraints, so they do survive beyond the defining assembly.

Not to any other language. Those "constraints" disappear if I reference the assembly from C#.

Anywho, I'm not trying to disparage F#. It supports its own type system within the confines of what the CLR affords. If the CLR supported more generic type constraints I assume that F# would take advantage of them where it could.

@Ultrahead

If the CLR already supports enum/delegate generic constraints, why was it excluded from C#7?

El 22 jun. 2016, a las 1:34 p.m., HaloFour notifications@github.com escribió:

@FunctionalFirst

I'm not sure why a compiler enforced constraint is fake, but a CLR constraint isn't.

Perhaps "fake" was a bad choice of words. It's not a CLR generic type constraint, which is what C# supports. It's a different beast altogether.

F# stores metadata about compile-time constraints, so they do survive beyond the defining assembly.

Not to any other language. Those "constraints" disappear if I reference the assembly from C#.

Anywho, I'm not trying to disparage F#. It supports its own type system within the confines of what the CLR affords. If the CLR supported more generic type constraints I assume that F# would take advantage of them where it could.


You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub, or mute the thread.

@gafter
Member
gafter commented Jun 22, 2016 edited

@Ultrahead The CLR has no way to express the constraint that a type argument must be a proper subtype of System.Enum. The same issue exists for delegates.

We don't need a reason to exclude things from C# 7. We only need a reason (and resources) to include things.

@HaloFour

@gafter

The CLR has no way to express the constraint that a type argument must be a proper subtype of System.Enum.

IIRC, where T : System.Enum, struct would force it since System.Enum is not considered a value type.

However, no such facility for System.Delegate.

@gafter
Member
gafter commented Jul 5, 2016

@manishki007 This is not the place to make feature requests or proposals. Please open a new issue.

@pmunin
pmunin commented Jul 7, 2016 edited

Is using non-constant parameters and generics of custom attributes possible?
For example:

[MyCustomAttribute1(new AttrPar1(...))]
public object MyProperty {get;set;}

[MyCustomAttribute2<T1,T2>]
public object MyProperty2 {get;set;}

Here is example where this syntax sugar would make code much nicer:

[Validate(dt=> dt>DateTime.Parse("2010/7/1") && dt<DateTime.Parse("2016/7/1"))]
public DateTime MyDateTime{get;set;}

It could also help a lot in unit tests, when you need to declare InlineDataAttribute (XUnit) for Theory unit test. You could create mock instances right in parameters of InlineDataAttribute.

With current limitations it is solved via passing method name to attribute constructor or implementing interfaces on the class, both of which are ugly

#12377

@thomaslevesque
Contributor

Is using non-constant parameters and generics of custom attributes possible?

Generics might be possible, but I suspect it would require changes in the CLR.
Non-constant parameters don't really make sense; attributes are just metadata written in the assembly, so they can't change dynamically.

@pmunin
pmunin commented Jul 7, 2016

@thomaslevesque I just updated my question with example where combination of those features would be nice and make perfect sense

@HaloFour
HaloFour commented Jul 7, 2016

@pmunin

Attribute metadata is serialized directly into the assembly as a BLOB and must be recognized by the CLR in order to recreate the instance of the attribute at runtime. As such the supported types are very limited effectively to only what can be serialized natively. There's not much Roslyn can do itself to overcome this limitation.

As for your example, even if the syntax is useful you'll have to consider exactly what that means and how that translates into something that can be serialized into the assembly, deserialized back out at runtime, and how it can be inspected through reflection. A lambda doesn't make any sense there because there's no way that you'd be able to extract any meaningful information out of it. An expression tree might make more sense, but there are still a lot of pieces to get the syntax that you've described to function probably as you'd expect.

@pmunin
pmunin commented Jul 7, 2016 edited

@HaloFour, the ugly workaround for solving all those limitations is to use some Type, so
[Validate(dt=> dt>DateTime.Parse("2010/7/1") && dt<DateTime.Parse("2016/7/1"))] will have to be [Validate(typeof(AttrConstructorParameters1))] with AttrConstructorParameters1 class implemented separately from ValidateAttribute.

I don't see why Roslyn cannot help generating that class (AttrConstructorParameters<P1,P2,...>) dynamically transparently for developer, so he does not have to produce tons of typical hardly readable code?

So invisibly for developer eventually [Validate(v=> ...)] can be converted behind the scene to something like this:

[Validate(typeof(<AttrConstructParameters1>))] 
...//property declaration



class AttrConstructorParameters1 //invisible (nested?) class
{
    public Func<object, bool> Parameter1 = new Func<object,bool>( v=> ... );
}

There are bunch of invisible class generation happens for anonymous delegates, yield return, await,... Cannot it be used here similar way?

@HaloFour
HaloFour commented Jul 7, 2016

@pmunin

That sounds pretty kludgy, and that attribute metadata isn't particularly useful. You can't inspect the actual metadata, you just get an opaque type handle which doesn't provide any real information about how the validation works.

If this is a problem to be solved I'd rather see some coordination with the CLR/BCL teams to get expression trees supported as assembly metadata. Then the compiler could translate the lambda into an expression tree and serialize that into the metadata. Tools could read the expression tree out of the metadata in order to utilize it.

Alternatively, [ValidateLessThan("2016/7/1"), ValidateGreaterThan("2010/7/1")].

@optikos
optikos commented Jul 11, 2016 edited

@marchy

nullability is the single biggest thing that has happened in the programming world this decade

"Not null" compile-time enforcement might have gotten more popular this decade, but the pioneer in widely-utilized languages (beyond the research community) for "not null" compile-time enforcement is Ada 2005 in the prior decade—hence, your point moreover!:

Ada 2005 Rationale for null-exclusion

@vbcodec
vbcodec commented Jul 21, 2016

@optikos
Nullability is only somewhat helpful. Async support is many magnitudes more important, the same level as generics if not higher.

@MichaelKetting

@vbcodec To be honest, I believe this to be highly subjective statement.

Personally, I haven't had more than a handful cases were async is actually helpful. On the other hand, the argument checks in my codebase number number several thousand (not counting the checks for strings that shouldn't be null or empty) and even a short trace will result in 6 or even 7 digit counts of null checks. There's also the quite popular Fody Nullguard and the ReSharper NotNull annotation, all done in effforts to deal with reference types that should never be passed or returned as null.

As I said, a highly subjective preference and very likely dependent on the sort of application you're developing.

@orthoxerox
orthoxerox commented Jul 21, 2016 edited

@Marusyk I don't think Java-like checked exceptions will be implemented in C#: http://www.artima.com/intv/handcuffs.html

Also see http://joeduffyblog.com/2016/02/07/the-error-model/ for the relatively recent exploration of error models.

@gafter
Member
gafter commented Jul 22, 2016

@Marusyk Checked exceptions are not on our plans for C# 7.

@JohnnyBravo75

@pmunin
[Validate(dt=> dt>DateTime.Parse("2010/7/1") && dt<DateTime.Parse("2016/7/1"))]
Mixing code and metadata seems not a good idea for me.
Attributes are metadata, logic is in the code.

@elisee
elisee commented Jul 24, 2016 edited

We have Buffer.BlockCopy as a memcpy equivalent for fast raw copy. Any chance we could see a Buffer.BlockSet to mirror memset, as a fast raw initialization mechanism?

Basically, expose a way to generate the InitBlk op code at compile-time, without resorting to dynamic IL generation tricks. Seems like it would be well in tune with the work on ref returns / ref locals, which avoids unnecessarily slow copy operations, making gamedevs happy ^_^.

EDIT: It just dawned on me that maybe this is more .NET-related than C#. Please kindly let me know if this was the wrong place to post this proposal.

EDIT2: Submitted as dotnet/coreclr#6439

@gafter
Member
gafter commented Jul 24, 2016

@elisee That sounds like a library request, not a language request. Library requests belong over at the https://github.com/dotnet/coreclr repository. New language feature requests are best submitted as new issues rather than as comments on our plans for C# 7.

@jamesqo
Contributor
jamesqo commented Jul 26, 2016

@gafter

Library requests belong over at the https://github.com/dotnet/coreclr repository

I think you mean https://github.com/dotnet/corefx.

@jamesqo
Contributor
jamesqo commented Jul 26, 2016

@whoisj The code for Buffer is in CoreCLR, but API requests should be made in CoreFX. (I know since I made a request in CoreCLR once and got told to submit it to CoreFX... too lazy to find a link now since I'm on mobile.)

@gafter
Member
gafter commented Aug 25, 2016

See https://blogs.msdn.microsoft.com/dotnet/2016/08/24/whats-new-in-csharp-7-0/ for a very up-to-date status.

@OJacot-Descombes

Do the tuples work with params?

void m(params (string s, int i)[] args) { }

call with

m(("a", 1), ("b", 2), ("c", 3));

@soroshsabz

ITNOA

Hi,

Why immutability dose not important as C++ or even Java in C#?

Some feature like Allow readonly modifier on local variables, not just properties can be more powerful C#.

thanks

@HaloFour
HaloFour commented Sep 9, 2016

@soroshsabz See #115. But it didn't make the cut of features slated for C# 7.

@soroshsabz

@HaloFour thanks for response, But I think language version changing must be very big event. I prefer a fuller and mature to come later rather than sooner come but immature. language must be very powerful, well defined in semantic and stable.

@alireza-naghizadeh

We need inline default-instance creator, Like this:

myObject.MyStringList??.Add("something");

The '??' here, will create a default instance for MyStringList...
In C# 6:

myObject.MyStringList = myObject.MyStringList ?? new List<string>();
myObject.MyStringList.Add("something");

@MadsTorgersen

@alireza-naghizadeh
alireza-naghizadeh commented Sep 12, 2016 edited

I don't know why someone are disagree with my previous suggestion! But, I suggest another solution:

myObject.(MyStringList ?? new List<string>()).Add("something");

What do you think?
I want to do "Add" and "New" in one line! What suggestions, please?

@MadsTorgersen

@alireza-naghizadeh
alireza-naghizadeh commented Sep 12, 2016 edited

This is an another suggestion too! The null-coalescing assignment operator.
If MyStringList is null, then create an instance and assign to it...

(myObject.MyStringList ??= new List<string>()).Add("something");

What about this one?

@MadsTorgersen

@stepanbenes
stepanbenes commented Sep 12, 2016 edited

@alireza-naghizadeh
C# 6: (myObject.MyStringList ?? (myObject.MyStringList = new List<string>())).Add("something");

And what is wrong with two lines?

@Cologler
Cologler commented Sep 12, 2016 edited

@alireza-naghizadeh
myObject.MyStringList??.Add("something"); look like myObject.MyStringList?.Add("something");

@realbart
realbart commented Sep 12, 2016 edited

@alireza-naghizadeh
You know you can do:
(myObject.MyStringList??(myObject.MyStringList = new List<string>())).Add("somehing");
right?

edit
awww @stepanbenes you beat me to it

@alireza-naghizadeh

@Cologler @stepanbenes @realbart

In myObject.MyStringList?.Add("something"); if MyStringList is null, then do nothing!
What is your opinion about this?

(myObject.MyStringList ??= new List<string>()).Add("something");

or another usage, like this: (We can write codes in many ways, but we want better coding in C# 7)

myObject.MyStringList ??= new List<string>();
@stepanbenes

@alireza-naghizadeh
If you want better code, write this:

if (myObject.MyStringList == null)
{
    myObject.MyStringList = new List<string>();
}
myObject.MyStringList.Add("something");

Better does not necessarily mean shorter.

@alireza-naghizadeh

@stepanbenes

Better does not necessarily mean shorter.

That's right... After many posts, I found this suggestion (??=)...
I think if we have this operator, we can write shorter and more beautiful codes...
Like (+=), (-=), ... We can have (??=) means assign if the left is null...
Agree with me? This is just a suggestion...
Thanks

@stepanbenes
stepanbenes commented Sep 12, 2016 edited

@alireza-naghizadeh
I thought you want to add this operator: ??.
Anyway, I have different view than you.
For me beautiful code is simple code.
Ideally one thought per line.

@alireza-naghizadeh
alireza-naghizadeh commented Sep 12, 2016 edited

@stepanbenes @Cologler @realbart thank you for your attention.
Now, my suggestion is The null-coalescing assignment operator.

Usage: (Assign if the left is null)

myObject.MyStringList ??= new List<string>();

or

(myObject.MyStringList ??= new List<string>()).Add("something");

@MadsTorgersen @ygc369 @thomaslevesque

@thomaslevesque
Contributor

@alireza-naghizadeh please create a separate issue for this suggestion

@stepanbenes
stepanbenes commented Sep 12, 2016 edited

@alireza-naghizadeh
Ok, Why not. I don't have strong opinion on this operator. Although, I don't like the nature of assignment operators in C# - being able to use them in expression and also as a statement. This new operator would encourage to use this practice more.
I think the team should spent its time on more important features than this sugar.

@Cologler

@alireza-naghizadeh myObject.MyStringList = myObject.MyStringList is bad idea when not null.

@jnm2
jnm2 commented Sep 22, 2016

@Cologler agreed but ??= would still see a ton of use from me for other scenarios, like return x ?? (x = CalculateX());

@csharpbird

It seems that the following codes don't works in Visual Studio 15 Preview4
``var areas =
from primitive in primitives
let area = primitive switch (
case Line l: 0,
case Rectangle r: r.Width * r.Height,
case Circle c: Math.PI * c.Radius * c.Radius,
case *: throw new ApplicationException()
)
select new { Primitive = primitive, Area = area };

@HaloFour

@csharpbird

The expression form of switch did not make the cut for C# 7.0. I expect that it will be revisited by the next major version if not a point version.

@Obertyukh

Look at my proposal for nullability guarantee, may be it will allow us to have real non nullable references in arguments and fields and back compatibility with C#6 libs and users.

#5032 (comment)

@Acerby
Acerby commented Oct 10, 2016

A small thing:
With the new provisions for non-nullable types - I would like to suggest adding support to allow:

var x = (condition) ? (T?) (nonNullableExpressionOfTypeT) : null;

to be simplified to:

var x = (condition) ? (nonNullableExpressionOfTypeT) : null;

@jnm2
jnm2 commented Oct 10, 2016

Yes please. I don't even care that it would have to infer types outside-in; this one pattern is such a common pain.

@ufcpp
ufcpp commented Oct 11, 2016

@Acerby related: #1419, #13602

@Andrew-Hanlon

There is a very common pattern in c# where IDisposable is misappropriated to provide an easy way to encapsulate code while ensuring that a final action is executed. A common usage is in 'DeferRefresh' type methods, but there are countless examples.

This pattern is extremely useful, but has negatives:

  1. This usage muddies IDisposable's strong guarantee about the necessity of cleanup.
  2. As a consumer you are left to make assumptions about unmanaged resources.
  3. A class that has disposable members of this type will unnecessarily flag code analysis.

There needs to be an additional interface that can be used within a using block with the opposite guarantee, i.e. "Cleanup is not required".

While naming is entirely subjective, something like IFinally would seem appropriate.

@kornman00

@Andrew-Hanlon I feel an attribute would be a better solution to this, rather than add more rules or interfaces. It could be used to silence analyzers about members that don't truly need to be disposed of, and when users are referring to the API itself or its documentation could see that "oh this implements IDisposable for scope exit purposes"

@Andrew-Hanlon

@kornman00 An attribute is certainly an option, but I disagree that its a better solution. I think most people write code to be as self documenting as possible, and while an attribute and note in the documentation is nice, interfaces are supposed to represent contracts, and IDisposable is both a very important contract and one which is routinely broken.

@pmunin
pmunin commented Nov 21, 2016 edited

Is there any feature requested of dynamic interface mappings? Let's say I have an

public interface IHasName { string Name{get;} }

And I have POCO:

public class ObjectWithName 
{  
   //...other members
   public string property Name{get;set;}
   //...other members
}

Since ObjectWithName is POCO - it does not implement IHasName and I don't have any control over it. As a developer, I'd like to cast in some native way ObjectWithName to IHasName without writing my custom proxies/wrappers to get it supported on compilation level. E.g.:

ObjectWithName objectWithName = LoadSourceObject();

IHasName namedObj1 = objectWithName as IHasName; //returns null
IHasName namedObj2 = objectWithName mapTo IHasName; //returns dynamically mapped IHasName

Right now developers have to use stuff like http://www.castleproject.org/ and create a bunch of code to make it happen. It'd be great if C# could do it natively.
As far as I know Typescript can work that way, when we can any Javascript object to interface and call any of its members accordingly - if the member does not exist it will throw error in runtime.

@HaloFour

@pmunin

#10757, #9132 and #7844. Today the best the compiler could do is to generate that wrapper for you and that wrapper would lose its connection to the original class (e.g. you couldn't cast the IHasName instance back to an ObjectWithName instance). Personally I think I'd prefer exploiting source generators to auto-generate these proxies than to have the compiler bake that concept in.

@xied75
xied75 commented Nov 21, 2016

@pmunin not really want to pollute the thread, would this https://github.com/ekonbenefits/impromptu-interface help? I know it's not a language feature, but been around for ages.

@OJacot-Descombes

@pmunin: In C# there is no need to create a wrapper. You can simply derive a class that pretends to implement the interface. The inherited members are automatically considered to be implemented, if they match.

I used this behavior in order to implement Views (simplified):

public interface IView
{
    void Close();
}

public partial class MyView : Form, IView
{
    // Since the base class declares a Close method, IView is implemented.
}
@yaakov-h

@OJacot-Descombes That only works if you can modify the assembly containing MyView. I think what @pmunin is after is more akin to the extension capabilities in Swift.

@pmunin
pmunin commented Nov 22, 2016 edited

@xied75 - ImpromptuInterface is just another implementation of custom proxy similar to Castle. If you see nuget package was last published in 2013, they don't even support latest frameworks .NET Core, Standard. And I disagree with @HaloFour - I believe functionality like this should be native, like it is in Typescript.

@paulomorgado

@pmunin

I believe functionality like this should be native, like it is in Typescript.

Except that TypeScript is a totally different language running in a totally different runtime.

TypeScript is transpiled to ECMAScript which allows, pretty much, anything. In fact, one could argue that the job of TypeScript is to limit the crazy of ECMAScript.

On the other hand, C# is compiled to IL which runs on the CLR. I'm not an expert on any of the latter, but I suspect that it would be impossible to do that as a "native" language feature without seriously impacting every program out there.

@pmunin
pmunin commented Nov 30, 2016 edited

One more feature request: Nested types everywhere. Right now developer can create nested type only in Classes and Structs. Why not to allow nesting for any type, especially for Interfaces? It would be nice to be able to refer some enum or datacontract class/interface declared in the service interface.

@HaloFour

@pmunin

I'd suggest creating a new proposal for this. The comments of this issue aren't scoured for work items.

Note that nested types within interfaces were mentioned as a part of #2238, but not under their own proposal. There is no limitation against this in the CLR, and VB.NET has always supported it. Seems that not permitting such nested types was a design decision in C#. It is explicitly mentioned in the .NET design guidelines that nested types shouldn't be used for logical grouping and shouldn't be used if the type is likely to be used outside of the declaring type. A type nested under an interface would violate both of those guidelines. As to whether those arguments still hold 16 years later is another question.

@pmunin
pmunin commented Nov 30, 2016 edited

One more request (please point to proposal if exist): Field initializers should have "this" in context. In many cases we developers still have to use constructor to initialize values, just because we don't have access to "this" in field initializers. Example of expected behavior:

public class MyGraph
{
   public class Node
   {
        public Node(MyGraph parent)
        { ...}
   }

   public Node Root {get;} = new Node(this);
}

Foreseeing the question about the order of field initializers execution and how to know which fields of "this" are already initialized and can be used to see what to expect being initialized. Here is an example that demonstrates situation:

public class MyClass
{
     DbConnection connection = new DbConnection();
     string[] Names {get;} = this.connection.LoadNames();  //assumes "connection" to be initialized
}

I see 2 approaches:
a) Developer friendly way (Preferable): Execute initializers following the field declaration order. So if "connection" declared before "Names", then during "Names" initialization, connection is available. People can ask what to do in case of partial classes. I would suggest: in case of partial class initializers match the execution order to the order of filenames, because that's how compiler will join those files.

//file1.cs
partial class MyClass
{
     string[] Names3 {get;} = this.connection.LoadNames();  //NullReference
}

//file2.cs
public partial class MyClass
{
     string[] Names {get;} = this.connection.LoadNames();  //NullReference
     DbConnection connection = new DbConnection();
     string[] Names2 {get;} = this.connection.LoadNames();  //Success
}

//file3.cs
partial class MyClass
{
     string[] Names4 {get;} = this.connection.LoadNames();  //Success
}

b) Simple, but hostile way: even though field initializers were executed and values calculated - compiler can just keep fields unassigned until all initializers executed, right before execution of constructor. This would be suckier than the option "a", but at least we'll have link to "this" assigned and can do the workaround using Lazy:

public class MyClass
{
     DbConnection connection = new DbConnection();
     Lazy<string> Names {get;} = new Lazy<string>(()=>this.connection.LoadNames());
}

Regardless of the approach, having any of those two options would be better than having none, and having to trash up the constructor.

This is definitely doable just on compiler level (no changes to CLR required) and it also does not break existing code, because now devs cannot use "this", all initializers are basically static methods code.

Let me know what you think guys.

@thomaslevesque
Contributor
thomaslevesque commented Nov 30, 2016 edited

Foreseeing the question about the order of field initializers execution and how to know which fields of "this" are already initialized

It doesn't matter which fields are already initialized; the constructor hasn't run yet, so this itself isn't considered initialized at this point, and is not safe to manipulate. If you can pass this to another class as in your example, Node will receive a reference to a MyGraph instance whose constructor hasn't run yet, but it won't know that, so it's likely to do something unsafe with the object.

@HaloFour

@pmunin

Also mentioned in #2238. This is another place where VB.NET differs as it does allow referencing Me in field initializers. But VB.NET takes a different tact that C# in that it inlines the field initializers after the call to the base constructor whereas C# inlines them before that call. As such this doesn't exist as the type hasn't been initialized. This is important as in C# if the base class calls an overridden virtual method that method can reference that field and expect it to be populated whereas with VB.NET it would remain uninitialized.

Changing this to have the C# compiler conditionally inline the initialization before or after the base constructor call would be possible but it would require the compiler to keep track of the dependencies between those fields to ensure that they are initialized in the expected order. That might lead to confusion as to when the fields are expected to be initialized and where they may be referenced, which is limited but at least predictable today.

@pmunin
pmunin commented Nov 30, 2016 edited

@thomaslevesque I understand how it works right now. If it was not clear enough from my post - my point is that current design/implementation is not user-friendly enough (where developers are the users of your platform), because it does not cover specified scenarios, which I believe are not too rare. I suggested how you can change your platform to cover it. I don't see any feasibility issue that stops to evolve the design and execute field initializers as a constructor like code, similar way, which just does not have to sit in constructor, when instance of parent class already created.

@thomaslevesque
Contributor

I don't see any feasibility issue that stops to change previously made design decision and execute field initializers as a constructor like code

Oh, it would certainly be feasible. But it might be a breaking change, and there was a good reason for the initial design decision (see these blog posts).

@jnm2
jnm2 commented Nov 30, 2016 edited

@thomaslevesque

Foreseeing the question about the order of field initializers execution and how to know which fields of "this" are already initialized

It doesn't matter which fields are already initialized; the constructor hasn't run yet, so this itself isn't considered initialized at this point, and is not safe to manipulate. If you can pass this to another class as in your example, Node will receive a reference to a MyGraph instance whose constructor hasn't run yet, but it won't know that, so it's likely to do something unsafe with the object.

From a language perspective, how is this any different from passing this to another class in the ctor body? If anything, I think this makes his point stronger. =)

@jnm2
jnm2 commented Nov 30, 2016 edited

Fwiw this access in initializers has my vote. Few things are as consistently aggravating as having to refactor into the ctor body.
I can't think of a single case where it matters to me if the initialization is inlined before or after calling base.

@pmunin
pmunin commented Nov 30, 2016

just created proposal #15610

@HaloFour

@jnm2 @pmunin

Seems it all boils down to the following:

If the constructors and initializers run in their actual order then an initialized readonly field of reference type is guaranteed to be non null in any possible call. That guarantee cannot be met if the initializers run in the expected order.

Allowing for field initializers to execute after the base constructor would nullify this guarantee. So any argument would have to demonstrate why that guarantee is no longer necessary.

@jnm2
jnm2 commented Nov 30, 2016

@HaloFour answered your copy.

@pmunin
pmunin commented Dec 3, 2016 edited

Few more requests:

  1. Declaring local variables or constants easier. E.g.:
myList.AddRange(var defaultItems = new[]{1,2,3,4});
//and/or
myList.AddRange(int[] defaultItems = var anotherVar = new[]{1,2,3,4});

Created ticket: #15659

  1. Making compiler smarter with unassigned variables (or less strict) to compile the following code successfully:
Func<Node, IEnumerable<Node>> traverseTree = (n) =>
{
        return n.Children.Concat(n.Children.SelectMany(child=> traverseTree(child)));
};

//Right now it throws compilation error "Using an unassigned variable traverseTree"
// so people have to use an ugly workaround:

Func<Node, IEnumerable<Node>> traverseTree = null;
traverseTree = (n) =>
{
     return n.Children.Concat(n.Children.SelectMany(child=> traverseTree(child)));
};

Created ticket: #15660

  1. It would be awesome if compiler could become smarter about using var for delegates including the one using anonymous types, like it works with Generic delegate parameters:
var selector = (Node n) => {
     return new {Node = n, ChildrenCount = n.Children.Count };
}

created ticket: #15661

@thomaslevesque
Contributor

Declaring local variables or constants easier.

I agree. Although it's not extremely important to have this, it's inconsistent to be able to declare variables inline for out parameters but not for normal parameters.

Making compiler smarter with unassigned variables (or less strict) to compile the following code successfully:

I don't see the point. It's not very common to write recursive lambda expressions, and it's going to become even less common now that we have local functions.

It would be awesome if compiler could become smarter about using var for delegates including the one using anonymous types, like it works with Generic delegate parameters:

It's true that there's a gap for delegates that manipulate anonymous types; it's just not possible to declare such a delegate without using a helper method to do the type inference. However I think it makes sense that var x = (lambda expression) isn't legal, because the compiler can't decide which type of delegate it should be; the best it could do would be to pick Func<T, TReturn>, which might not be the right choice.

@MovGP0
MovGP0 commented Dec 3, 2016

@pmunin nested classes are indeed considered a useful feature by some developers. However, to my experience there are many ways how developers actually misuse them. Most important ones are:

  • nesting hides objects from the project tree, since they don't get their own file. Some project trees I've seen hide more than half of the classes!
  • nesting of large classes with lots of business logic in them, which blows up the file of the parent class to a degree that it becomes hardly manageable.
  • introduction of dependencies of the nested class from the parent class, which make refactorings literally "a pain in the a**" by wasting sitting time.
  • introduction of a lot of additional typing of the parent class name by exposing the nested types public and using them all over in the codebase.

Since a programming language should be restrictive in the ways a developer can mess up the code, I am all against methods that can introduce additional ways to mess up the code, without giving a convincing use case of a problem that can't be solved in another (cleaner) way.

@jnm2
jnm2 commented Dec 3, 2016

@thomaslevesque

I don't see the point. It's not very common to write recursive lambda expressions, and it's going to become even less common now that we have local functions.

Maybe not, but here is an awfully common pattern for me:

SomeDelegate oneTimeHandler = null;
obj.SomeEvent += oneTimeHandler = (s, e) =>
{
    obj.SomeEvent -= oneTimeHandler;
    // ...
};
@thomaslevesque
Contributor

@jnm2 you can also use a local function in that scenario ;)

@jnm2
jnm2 commented Dec 3, 2016

Oh I guess! I can hardly wait!

@NikChao
NikChao commented Dec 7, 2016 edited

Request: Bidirectional mapping feature:

At the moment if I want to map one object to another and back I'll write mappers as follows

public ObjectOne ToObjectOne(ObjectTwo obj)
    => new ObjectOne
    {
        Id = obj.Id,
        Name = obj.Name
        //etc
    }

public ObjectTwo ToObjectTwo(ObjectOne obj)
    => new ObjectTwo
    {
        Id = obj.Id,
        Name = obj.Name
        //etc
    }

I propose a bidirectional mapping feature which would use:

public ObjectOne ToObjectOne <=> ObjectTwo ToObjectTwo
{
   ObjectOne.Id = ObjectTwo.Id,
   //etc.
}

In my imagination, this syntax would compile to implicitly define the ToObjectOne and ToObjectTwo methods above.

#15735

@MovGP0
MovGP0 commented Dec 7, 2016

@nikChao I am unsure why you write such mappers in the first place. What advantage would your mapping feature have over AutoMapper?

@NikChao
NikChao commented Dec 7, 2016 edited

@MovGP0 Used to use Automapper but it turns out it tends to perform quite poorly (slowly) when you begin to map high numbers of objects, so now I tend to write my own.

@realbart
realbart commented Dec 7, 2016 edited

@NikChao what happens if the mapping uses methods, read-only properties or other more complex properties?

public static ObjectTwo ToObjectTwo(this ObjectOne obj) 
{ 
    return obj == null
    ? default(ObjTwo)
     : new ObjectTwo
    {
        Id = obj.Id,
        Name = obj.ToString(),
        FirstChild = obj.Children.FirstOrDefault().ToChildTwo()
        //etc
    }
}

(I often use Expression<Func<ObjectOne, ObjectTwo>>. Ik can cache the compiled result, to prevent a performance impact, but I can also quite easily feed this to linq like linq to EF and linq to SQL.

@MovGP0: even though Automapper has made some great performance improvments, I still hate it. Instead of compilation errors, you only see them at unit test time. Renaming a property breaks everything.
@NikChao , @MovGP0 you could easily create T4 templates that generate the two way conversion for you. Then you'll have compile time validation AND you prevent code duplication.

@NikChao
NikChao commented Dec 7, 2016

@realbart Hmm, perhaps read-only's only get mapped one way in this case and more complex Objects should still be able to be mapped bidirectionally. As for T4 templates, they are nice, but I see this as a syntactically easier approach for this sort of mapping.

@HaloFour
HaloFour commented Dec 7, 2016

@NikChao

Sounds like something that would be easily accomplished by source generators. Like T4 that would inject additional source into the project, but it would be effectively transparent. Either way, you should open a new issue for any proposals.

@MovGP0
MovGP0 commented Dec 28, 2016

@gdefraiteur seems like you are reinventing the squared wheel. use the nameof operator and dictionary initializers.

@gdefraiteur

and what about being able to use out or ref optional parameters?

@gafter
Member
gafter commented Jan 1, 2017

@gdefraiteur There is nothing in C# 7 about optional out or ref parameters.

@gdefraiteur

@gafter
Thats why i make the proposal no?

@HaloFour
HaloFour commented Jan 2, 2017

@gdefraiteur

If that's what you want to propose I suggest creating a new issue. These comments aren't tracked for consideration. There is already #186, but I don't know that I see a proposal dealing with ref parameters. It's probably very unlikely for anything new to be considered for C# 7.0 at this point, but maybe a release after that.

@gafter
Member
gafter commented Jan 2, 2017

@gdefraiteur we are no longer soliciting ideas for new features for C# 7.

@yaakov-h
yaakov-h commented Jan 2, 2017

@gafter Started on a C# 8 list yet?

@gafter
Member
gafter commented Jan 2, 2017

@yaakov-h Not really, though if we did have a corresponding list for C# 8, that would not be the place to make proposals.

@gulshan
gulshan commented Jan 5, 2017

@gafter Is https://github.com/dotnet/roslyn/blob/master/docs/Language%20Feature%20Status.md updated to reflect the current plan/roadmap/status?

@gafter
Member
gafter commented Jan 5, 2017

We don't yet have plans for future releases.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment