(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.
replace/original (part of generators) (Proposals: #5292, #5561)
Binary literals (Proposal: #215) [currently in future branch]
address of static method for unsafe interop code (Do we have a proposal?)
Generators (Proposals: #5292, #5561)
What has happened to variable declaration expressions (which almost made it into C# 6) and the semicolon operator?
Yeah. Declaration expressions was one feature I was really looking forward to in C# 6. I hope they're not dropped for good.
- Supersedes
What does that point mean? Searching for "supersedes" in the issues only returns this one. :)
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.
@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?
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.
@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.
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.
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:
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.
I guess the features that would reduce developer errors most are:
var! dog = new Dog();
let age = 26;
immutable int age = 26;
public immutable sealed class Dog { ... }
[Requires(...)]
[Ensures(...)]
requires ...
, ensures ...
@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.
Your strong interest list makes me very happy.
@seanfreiburg How would that differ from the ??-operator?
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)
@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.
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.
@dsaf https://github.com/dotnet/roslyn/issues/2136#issuecomment-95434384:
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.
What about support for auto generated object composition
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.
Reference to constant parameters as in C++ would be a suggestion from me.
@GoEddie for practical purposes this is covered by the Tuple proposal
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.
@Eirenarch thanks! I have updated 102 to point to the tuple proposal
_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.
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?
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" [email protected]
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
https://github.com/dotnet/roslyn/issues/2136#issuecomment-95560417.
@iainholder INPC is listed in #1677 as 'too specific; metaprogramming?'
One thing that would be extremely beneficial for Linq performance would be IExactSizedEnumerable
Python does this using a property called length_hint https://www.python.org/dev/peps/pep-0424/
IExactSizedEnumerable
= IReadOnlyCollection
.
+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 :)
https://github.com/dotnet/roslyn/issues/2136#issuecomment-95570818
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.
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.
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
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.
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
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.
@wesnerm Well neither is uint
but that hasn't stopped anybody. :smile:
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.
@MovGP0 Good point, at least F# already support units and we're working on something similar for the Java platform, too ;-)
Type providers :+1:
@MadsTorgersen: "Additional generic constraints" should also refer to #262 (which as stated above by @HaloFour already is supported by the CLR)
What about variable
declaration ?
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 https://github.com/dotnet/roslyn/issues/106
@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.
PLEASE PLEASE everything in the small but useful list!
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).
@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.
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.
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.
Immutable types #159 would also be amazing.
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.
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!
@JayBazuzi we only wanted them in nested private classes because of the arbitrary requirement that they couldn't be in a nonstatic class
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.
@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.
@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?
@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.
@RobertGBryan You should suggest that to the CoreFX Team. They consider possible API changes to the framework.
@RobertGBryan, that's a library issue, not a language issue. That won't be fixed by a new feature in the language.
@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.
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.
Why not Metaprogramming? :'(
+1 Type providers! Please!
@MadsTorgersen can u elaborate on "compile time attributes"?
Enum and generic constraints please so i can delete this project https://github.com/Fody/ExtraConstraints
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.
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 :smile:
+1 for structural typing. That would be awesome. Spoilt by TypeScript.
Excuse my ignorance, but what is INPC?
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.
@mcintyre321 thanks. Never used it :stuck_out_tongue:
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.
@khellang I think #154 could be considered Duck typing.
@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.
+1 for Nullability tracking (Proposal: #227)
+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.
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.
@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.
@HaloFour yay, thanks!
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/
@ehouarn-perret Additional constraints are explicitly mentioned in the opening post itself: "Small but useful" and "Interesting but require CLR support" sections.
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:
@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.
Shouldn't #1384 (Family AND Assembly access modifier) be on this list, given that it was going to be included in C# 6 but didn't quite make it? As a minor enhancement that doesn't require CLR changes, it probably belongs in the Small but useful bucket.
@badja It's not bucketed because Mads is probably still having nightmares after the wars on CodePlex over what word to call the operator.
@MgSam commented on Jul 1, 2015, 3:17 PM GMT+2:
@badja It's not bucketed because Mads is probably still having nightmares after the wars on CodePlex over what word to call the operator.
IMO it's better to have this feature even if the chosen keyword isn't perfect, than not have it just because the team and the community couldn't agree on a keyword.
IMO it's better to have this feature even if the chosen keyword isn't perfect, than not have it just because the team and the community couldn't agree on a keyword.
Just learn from C++/Cli folks and move on.
Just learn from C++/Cli folks and move on.
That was the initial plan... C++/CLI uses protected private
. C# 6 was initially supposed to use private protected
, but everyone hated it. That's what caused the fruitless debate to pick a different keyword.
@thomaslevesque
Can't please everyone. On the Internet it's more like "can't please anyone." I think they should just go with the same keywords as C++/CLI* and implement it. It's a minor win and being consistent should reduce potential confusion, although the use-cases are so limited it probably won't come up much anyway.
* Yes, I am aware that private protected
and protected private
are the same thing given that the modifier keywords are permitted to be in any order.
protectedandinternal
and protectedorinternal
is a nearly perfect choice. I can't understand why English speakers so care about the 'purity'.
Yes, protectedandinternal
and protectedorinternal
are very ugly, but they are very very CLEAR.
There will be 7 access modifiers:
public
protected
internal
private
protectedandinternal
protectedorinternal
protected internal
/ internal protected
(for backward compatibility)@knat Doesn't fit with how access modifiers are already specified in C#.
If C# doesn't just copy C++/CLI and implement with the original plan it's best to just leave the feature out because the "keyword wars" that ensued are the epitome of a waste of time.
@HaloFour I think the Roslyn team is capable of and should really make firm decisions like this. Whatever it's called as long as it's done.
I edited the list to reflect decisions from #3912 and #3910.
method references as implemented in java are very neat and prevent a lot of unnecessary lambda expressions.
method references as implemented in java are very neat and prevent a lot of unnecessary lambda expressions.
You mean doing something like that items.Where(IsValid)
instead of items.Where(i => IsValid(i))
? It's already possible in C# (actually it was possible before lambda expressions even existed in C#).
A nice thing that Java 8 does and C# doesn't, though, is allow constructors to be used as method references, e.g. items.Select(SomeClass::new)
. I'd like to see that in C#, but I suspect it would require some changes at the CLR level too, because currently you can't create a delegate directly from a constructor.
@thomaslevesque yes it's already possible but not from the outside of the class. something like this customers.Select(Customer::Name)
. However, you can create delegates from instance members via Delegate.CreateDelegate
.
@thomaslevesque yes it's already possible but not from the outside of the class
The fact that the method is in another class is irrelevant, as long as it's public. My example above would work just as well if IsValid
is in another class:
items.Where(Utils.IsValid)
items.Where(validator.IsValid)
something like this
customers.Select(Customer::Name)
Well, in this case it's a bit different, because Name
is a property, not a method (I assume). I think the point you're trying to make is that we can't reference an instance method this way if we don't have an instance? It's not something that I miss personally, but I see how it could be useful.
it's a bit different, because
Name
is a property, not a method (I assume).
I'm relying on the fact that properties are internally implemented as methods, e.g. get_Name
in this case.
I'm relying on the fact that properties are internally implemented as methods, e.g.
get_Name
in this case.
Yes, but there are two methods (for read-write properties): get_Name
and set_Name
. Which one would Customer::Name
refer to? I'm not against such a feature, but it would have to be carefully thought through.
Which one would
Customer::Name
refer to?
It should be inferred from usage, but yeah there are a lot of details to think of.
@thomaslevesque
Which one would Customer::Name refer to?
Getter is a Func<>
and setter is an Action<>
so it should be possible to resolve based on context. Let's not forget however, that lambda notation is used against properties to capture their name and other information which is useful for implementing DSLs (e.g. EF Code-first maps). How would that be affected? Would reduced form be still an expression?
@thomaslevesque
A nice thing that Java 8 does and C# doesn't, though, is allow constructors to be used as method references, e.g. items.Select(SomeClass::new). I'd like to see that in C#, but I suspect it would require some changes at the CLR level too...
Not necessarily, latest F# has worked around that somehow:
https://www.visualstudio.com/en-us/news/vs2015-vs#fsharp
_Constructors as first-class functions - Class names can now be used as first-class function values, representing the constructor(s) for that class._
Not necessarily, latest F# has worked around that somehow:
It does so by implicitly creating an anonymous function that calls the constructor, so it's essentially the same as using a lambda. Still, the syntax is lighter, so it would be nice to be able to do that in C#.
I want to think about another feature for the list, I think the interest is not so small.
Weak references (for events or more common approach)
@alrz
Similarly, I had proposed a shorthand syntax to writing those kinds of simple lambdas by using a sigil in place of the argument list (#3561). For example, .Select(customer => customer.Id)
might be shortened to .Select(@.Id)
. A method reference syntax would be more flexible but a little more verbose in these specific cases.
another feature that would be useful is ability to use the type void
in generics. It totally eliminates the need for non-generic and generic interface hierarchies. as does unit
for F#.
@alrz Your suggestions deserve to be separate tickets, would you like to create them?
@dsaf sure, when I come up with more details I will. thanks.
@alrz IIRC that's not really possible as void
denotes a lack of type which would fundamentally alter the IL that would need to be emitted, but with generics the IL needs to be identical regardless of the generic type arguments. In any case it would involve some serious changes to the BCL. If there was a solution you'd probably see the Java version where Void
is a proper type, like unit
, which can be used as a generic type parameter, and you'd be required to pass null
as it's value. Rx did something similar, defined System.Unit
which is a struct that has no value.
@MadsTorgersen
How about #3371 ?
@h82258652 #3371 is now tagged "up for grabs". We'd welcome community contributions here.
@MadsTorgersen
Also, would you all please consider adding Undefinable* type wrapper structs outlined in #4357?
Thanks!
Add inline interface implementation and inline override class this is helpfull
An example in java that provide a way to have a "Fluent visitor".
The idea is to chain visitors like creating expression of visitors.
The return type "Anonymous type of interface" can be an object visitor or whatever and we can reuse it to access members ex:"isNative()" or we can create an other call to another object.
In c# the member types of an anonymous object are not accessible outside the scope of the function and they can't implement an interface to be passed to another function.
public interface IColumn {
<T extends IColumnVisitor> T accept(T columnVisitor);
};
public interface IColumnVisitor {
void visit(NativeColumn nativeColumn);
void visit(CalculatedColumn calculatedColumn);
}
public class INativeColumn implements IColumn {
<T extends IColumnVisitor> T accept(T columnVisitor) {
columnVisitor.visit(this);
return columnVisitor;
}
};
public class ICalculatedColumn implements IColumn {
<T extends IColumnVisitor> T accept(T columnVisitor) {
columnVisitor.visit(this);
return columnVisitor;
}
};
public final class ColumnTypeDetector {
void boolean isNative(IColumn column) {
return column.accept(new IColumnVisitor(){
private boolean isNative;
private boolean isNative() {
return isNative;
}
void visit(NativeColumn nativeColumn) {
isNative = true;
}
void visit(CalculatedColumn calculatedColumn) {
isNative = false;
}
} ).isNative();
}
};
@Kingnaoufal I think that for your example, pattern matching (#206) would be a better choice:
c#
bool IsNative(IColumn column)
{
switch (column)
{
case NativeColumn nativeColumn:
return true;
case CalculatedColumn calculatedColumn:
return false;
}
}
@svick
I agree if i want to drop the two functions and use pattern matching, but my point is not about this part of the code, it's about reusing anonymous object to chaining them and accessing there members out of the creation scope.
In c# is not possible to do that "I create some wrapper that emit IL to emulate that" and i found it useful when i want to build system that chaining expressions and reusing them later.
I think if i'm not wrong it's an easy feature to add to the compiler and add more capability to let the user choose where and when they want to create derived instance whitout writing a new class.
Second point is to let us changing default behavior of class by create an in place override of the object, i found it useful when i want to debug a library whitout source code.
We can imagine a pletory of scenario when these language shortcuts can be useful.
Regards,
Naoufal
@Kingnaoufal We do not appear to have an issue/proposal corresponding to what you're suggesting.
@Kingnaoufal I assume that you're referring to allowing anonymous classes implement an interface and to provide that implementation. Check out proposal #13.
@MadsTorgersen
If you would, please also consider #4436.
Thank you.
@erik-kallen,
about semicolon: it should be optional, like Scala. If I'm not wrong Scala use semicolon inference.
Another thing I'd like to see is the removal of "{...}" curly braces for everything, except methods or multi-line closures.
:smile:
@gsscoder Not sure if you're being serious. Issue 2974 (intentionally not referencing it) already brought up eliminating the requirement for braces. There was also a lengthy conversation on CodePlex about implicit semicolons. I'd love to see the argument that can demonstrate why either massive effort (and resolving syntax ambiguities) are worth it beyond <whine>
but I don't like (semicolons/curly braces)<whine>
.
@HaloFour, maybe I was superficial, but I'm serious. I'll say it better: remove "{...}" for namespace declaration and types and leave it for methods and every construct inside it.
About semicolon I think it could be "easy" avoided for a great major of cases. To me is just noise... :(
Thanks for the link, I've missed it.
@gsscoder
I can kind of see it for namespaces. A single namespace Foo;
declaration at the beginning of the file establishing the namespace for the entire file. Then you avoid the almost compulsory first indentation. Aside from compiler directives I don't think anything else in the language is file-scoped, though. There is the potential ambiguity as to what would happen if the compiler hit a second namespace
directive in the middle of the file, whether that would establish a new namespace for the remainder of the file or a nested namespace. Those concerns are probably minor and could probably be addressed by simply not permitting statement namespace directives to appear more than once within a file.
Types are probably similar. The vast majority of the time (high 90s percentile) I imagine people adhere to file-per-type conventions. I personally don't like the idea of seeing a type without braces, but that's more a question of style as that's what I'm used to (Scala still looks like APL-lite to me). I assume that you'd propose that any member appearing after the class declaration would just belong to that class?
namespace Foo;
public class Bar
public string Name { get; set; }
Something about that just doesn't feel right. But feel free to toss a proposal out there as a separate issue if you want to advocate it.
As for semicolons, considering that they couldn't entirely be removed without changing some other grammar to avoid ambiguities and that removing them in only most/some cases would just be confusing I can't imagine that the conversation is much more than a non-starter. I've always been of the opinion that if you want a different grammar there are a couple dozen other languages targeting the CLR, including Scala.
Is there a separate issue for "Syntax for lists, Syntax for dictionaries"? I was wondering what will happen to ImmutableArray
, ImmutableList
, ImmutableDictionary
?
@HaloFour
...I don't think anything else in the language is file-scoped...
How about namespace imports using
?
Regardless, I think this thread is becoming incomprehensible, someone above already mentioned #595.
Thanks for the link @dsaf, it's interesting.
I think that the overall philosophy has nothing todo with turning C# into F (always I hear this objection): but make the syntax terser and modernize a C# from its root.
I think it's now mature enough to lost its "coupling" from C-ish style, poorly speaking and in general.
I want spend more time thinking than typing and even more time handling data than building software structure that handle the program itself (this second part is an allusion to increment the FP constructs in C# or at least add more sugar like quoted in various proposals).
@gsscoder I just had a very brief look at two allegedly "modern" languages - Swift and Rust. Both seem to keep using curly brackets in a lot of places and Rust insists on using semicolon. ML is about as old as C, so F# definitely doesn't have a "modern" syntax.
@dsaf, I was only anticipating people that see any removal from C# a walk toward making it F#.
I love F#, OCaml and in general ML-family languages, but making such thing (turning C# -> F#) makes no sense to me too.
I doesn't understand what's the problem of removing ;
where it can be removed...
I don't know Swift very well, but I know that designers have embraced various functional constructs.
The same for Rust: it's a language with a lot of cool features but I think that its macro-system is too complex (it seems to me a brand new language).
Yes ML-stuff is old, but is good and leads to clean code. I've no problem programming in a language without ;
and without an abuse of {...}
.
But I'm agree that at some points, some syntax choice are just a matter of taste. Or maybe in past to simplify lexer/parser of the compiler...
In the end the things that really count are the ones around the type system. But I insist: I personally like terser syntaxes.
@gsscoder I think occasionally requiring semicolons and allowing them to be omitted elsewhere would be the definition of "unclean". It requires the developer to have to remember the idiosyncrasies of the language. Beyond that it's nothing but a preference.
@dsaf Oops, you're right about using
directives. And you're also right about this thread being way too polluted.
@HaloFour, why difficult? Just use it when you want to place two expressions in the same line.
A reference on the argument.
PS: I add that I don't want C# to become like Scala that for me has too features...
Don't you mean using
directives, @HaloFour?
Microsoft has announced that, in a future version of TSQL, terminating statements with semicolons will be mandatory.
@gsscoder I'm willing to bet that there are more ambiguities than that. Either way, there is no benefit to making the semicolon optional _sometimes_. There are liabilities, both in the work necessary to change how the language is parsed and in that every developer now has to remember when they can and can't omit those semicolons.
@paulomorgado You're right, updated my comment to be clear. IIRC, ANSI SQL requires semicolons. T-SQL is playing catch up, although many newer statements already require that the previous statement at least be semicolon terminated.
@HaloFour, if you are referring to CTEs, the problem is with the with
keyword and the grammar. Many times it is not possible to determine if the with
keyword is the start of a CTE or if it belongs to the previous statement. Thus explicitly terminating the previous statement with a semicolon solves this.
I'm not a JavaScript/ECMAScript developer, but I wouldn't be surprised if at some point semicolons became mandatory also for JavaScript/ECMAScript.
@HaloFour, @paulomorgado, however the trend seems to be just that (removal of ;
), excluding some minor exceptions.
I'm sure you serious data to back that up, @gsscoder.
@paulomorgado, what does it mean?
I don't see that trend at all. But I'm willing to assume that it's because I don't know what everyone is doing and thinking.
@paulomorgado, not everyone... But language and language designers: it's absolutely something less small to know and monitor, I think.
@gsscoder
I don't like the idea of removing curly braces, especially from classes. What if you have nested types? This seems like a fundamental change to the language.
Consider:
public class OuterClass
private class InnerClass
public void DoSomething() {}
public void DoSomethingElse() {}
How is the compiler suppose to figure out that the above is actually suppose to be:
public class OuterClass
{
private class InnerClass
{
public void DoSomething() {}
}
public void DoSomethingElse() {}
}
Also, removing the semi-colons seems akin to removing periods from the English language. I'm all for conciseness, but this has the makings of the start of trying to mutate C# into a different language entirely.
I'm not sure that the compiler could figure out that the following:
using System;
public class Program
{
private static Subordinate subordinate1 = null
private static Subordinate subordinate2 = new Subordinate("Subordinate2")
public static void Main()
{
var sub = Program.getSubordinate()
Console.WriteLine(sub(null).Message)
}
public static Func<object, Subordinate> getSubordinate()
{
if (Program.check_something())
return
Program.get_something
(
0,
true,
string.Empty
)
// WARNING!!!! Uh oh? there is an ambiguity here.
// Are we calling the return of get_something with this
// next line before returning?
(Program.subordinate1??Program.subordinate2).get_something()
return obj=>new Subordinate("New sub 2")
}
public static Func<object, Subordinate> get_something(int arg1, bool arg2, string arg3)
{
return obj=>new Subordinate("New sub")
}
public static bool check_something()
{
return new Random().Next(1, 100) < 50
}
}
public class Subordinate
{
public string Message { get private set }
public Subordinate(string message) { this.Message = message }
public Func<object, Subordinate> get_something() { return null }
}
is actually suppose to be:
using System;
public class Program
{
private static Subordinate subordinate1 = null;
private static Subordinate subordinate2 = new Subordinate("Subordinate2");
public static void Main()
{
var sub = Program.getSubordinate();
Console.WriteLine(sub(null).Message);
}
public static Func<object, Subordinate> getSubordinate()
{
if (Program.check_something())
return
Program.get_something
(
0,
true,
string.Empty
);
(Program.subordinate1??Program.subordinate2).get_something();
return obj=>new Subordinate("New sub 2");
}
public static Func<object, Subordinate> get_something(int arg1, bool arg2, string arg3)
{
return obj=>new Subordinate("New sub");
}
public static bool check_something()
{
return new Random().Next(1, 100) < 50;
}
}
public class Subordinate
{
public string Message { get; private set; }
public Subordinate(string message) { this.Message = message; }
public Func<object, Subordinate> get_something() { return null; }
}
Note the warning comment in the version without semi colons. How does the compiler know that we are not calling the Func<object, Subordinate>
returned by get_something
method of the Program
class with the next line where we are applying a null conditional operator to two Subordinate
type fields before executing the get_something
method on that object that happens to return the same Func<object, Subordinate>
function type?
In other words are we expecting the equivalent of this:
return Program.get_something(0, true, string.Empty)(Program.subordinate1??Program.subordinate2).get_something();
or this:
return Program.get_something(0, true, string.Empty);
(Program.subordinate1??Program.subordinate2).get_something();
While this is a contrived case, it is still a very possible one.
Here is a dotnetfiddle of the this: https://dotnetfiddle.net/2ooBJO
@TyreeJackson
Also, removing the semi-colons seems akin to removing periods from the English language.
My favourite argument, because it's true :).
How is the compiler suppose to figure out that the above is actually suppose to be:
I think it would mean introducing the "syntactically significant whitespace" (yeach :unamused:).
@gsscoder
There appears to be a trend in designing new programming languages. They're almost as bad as JavaScript frameworks; everyone has their own. Those languages often don't require semicolons (and, as @dsaf mentioned, syntactically significant whitespace) because they're based on other languages with the same design. Perhaps those languages are so awful that people just feel the need to keep reinventing them.
Can you cite an example of a programming language that went from requiring semicolons to then allowing them to be optional, without requiring syntactically significant whitespace?
@HaloFour, I don't think this is possible... Obviously you need to switch to significant whitespace that's a thing I love, but as always in life is a matter of taste.
Removal of ;
and introduction of significant ws can let the language keep some curly brace {...}
too, which I'd like to be removed only for "top-level" constructs (ns, type definitions).
For example F# use significant/ws but use {...}
blocks for computation expressions (and obviously doesn't need ;
at the end of each line; but can use it for join two expression in the same line).
@gsscoder
The problem with significant whitespace is that it adds significant amounts of indentation.
Consider this next block of code using partial classes containing nested "top-level" constructs:
fourthLayer.cs
namespace MagicFramework
{
using System;
using System.Collections.Generic;
using System.Linq;
namespace subnamespace
{ partial class firstLevel
{ partial class secondLevel
{ partial class thirdLevel
{
public interface IFourthLevel
{
void DoSomething();
}
public partial class fourthLevel : IFourthLevel
{
public void DoSomething()
{
this.do_something_really_interesting_in_some_private_method
(
1,
true,
String.Empty
);
}
}
}}}}
}
Now look at the significant whitespace indentation version:
namespace MagicFramework
using System;
using System.Collections.Generic;
using System.Linq;
namespace subnamespace
partial class firstLevel
partial class secondLevel
partial class thirdLevel
public interface IFourthLevel
void DoSomething()
public partial class fourthLevel : IFourthLevel
public void DoSomething()
this.do_something_really_interesting_in_some_private_method
(
1,
true,
String.Empty
)
Now imagine the above with descriptive method names. It's hard enough managing horizontal whitespace usage and trying to keep things aligned left. Make the whitespace significant, and now things get really messy really fast.
In my opinion, the only significance whitespace should have is in helping to ease the task of humans reading code. That requires flexibility to determine when it is best to apply or not apply said whitespace. Once you make the whitespace compiler significant, that flexibility is lost and you now have to follow a set of rules.
In other words, I feel that, in terms of significance, curly braces are for the compiler and whitespace is for humans.
I think it would mean introducing the "syntactically significant whitespace" (yeach :unamused:).
I initiate the Internet revolt protocol here. :scream:
Obviously you need to switch to significant whitespace that's a thing I love, but as always in life is a matter of taste.
And it tastes terrible. If I wanted Python, I'd be coding in Python. :snake:
@TyreeJackson, if you keep everything in one file; but if you divide sources by types (+/-) I don't see problems.
I'd use two space indentation in sample like yours and anyway I see it as readable. I repeat it's a metter of taste, I'm sick of ;
and {...}
_super-presence_.
And if you read all my posts I'll keep {...}
for methods and internal constructs. I would also leave ;
for put two (or more) expressions in one line.
@whoisj, how code looks is far different from type system. Even with significant/ws C# will not became a language thought with a dynamic typing discipline like Python (which is a nice language full of cool libs and very cool for scientific computations).
I'm honestly surprised to see such a strong attachment to certain syntactic forms... But taste is taste and anyone has its own. I obviously respect every opinion different than mine. :smile:
C# has a nice type system, but it is not the best one available.
I'm a C# fan due to the combination of the C-like syntax and the type system.
@gsscoder
I'm not sure what you mean by "divide sources by types". If you are referring to having only one type definition per file, my example does that. The other classes are declared in other files. This is an example of class nesting using partial
classes to separate the nested types across separate files. With or without the separating of types into separate files, the proliferation of indentation will result in verifiable horizontal scrolling for some who do not have large horizontal resolutions. It will result in people needing higher resolution monitors in order to avoid scrolling. This is not a matter of opinion or style.
As far as the ;
for two or more expressions in one line, I've shown you an example that you have not addressed where there is ambiguity across multiple lines if the semi colon is omitted.
Here is the relevant snippet again. Does the following without semi-colons:
return
Program.get_something
(
0,
true,
string.Empty
)
(Program.subordinate1??Program.subordinate2).get_something()
resolve to:
return Program.get_something(0, true, string.Empty)(Program.subordinate1??Program.subordinate2).get_something();
or this:
return Program.get_something(0, true, string.Empty);
(Program.subordinate1??Program.subordinate2).get_something();
The semi-colon makes it clear to both human and compiler where one multi-line statement ends and another begins. Again, this is not simply a matter of style or opinion and is verifiable.
It all seems quantifiably too problematic.
Removing the curly brace block from the language would go to far. If you like significant whitespace you can always use a language like F# or Python.
Nested classes make a bad case for curly brackets, since nested classes are an antipattern. They violate SRP by making the parent class bloated. Therefore, nested classes should be avoided anyway.
The advantage of curly braces end semicolons is mostly in removing ambiguity for the compiler, especially when the programmer is in the middle of changing a few lines. It is a matter of taste if its better to have less ambiguity, and therefore more support from the compiler, or having a cleaner syntax with less clutter.
@MovGP0, I won't choose a different language because of whitespace presence or absence. As I said in various threads.
Partially introducing it in C# (and removing mandatory ;
) anyway could benefit readability, from my point of view. Saying just that.
Talking about F# I obviously love it and I think it's extremely valuable tool to use in conjunction with C#.
Python is a completely different language (dyn. typed), that, as said in other posts, is good to its own domains (a wide range, for what I know).
@MovGP0
Nested types are not an anti pattern and by themselves, they do not necessarily add bloat or violate the SRP.
When did perfectly good curly braces become "clutter?" Big deal, namespaces/classes "force" you to indent one column in an IDE sense -- syntactically significant whitespace really forces you to indent, or the code doesn't even compile. I love Python but C# is not Python and there is no earthly reason to start messing with the braces.
@MovGP0, i would allow only 1 level nested types to solve very particular needs... But more than one level of nesting is without doubt an anti-pattern. Or maybe something that make code unreadable.
@MadsTorgersen We should probably either update this or close it and open a new one with an updated list.
either update this or close it and open a new one
It's been a month. Still waiting.
@alrz that is not really very helpful.
We are working on a slightly more formal process. We'll let you know.
@gafter I see, thanks.
Something I feel languages like scala get a bit better is inferring types, especially when dealing with anonymous blocks. I was just playing around with some of the new ASP.NET DI (unrelated), but was really caught off guard by how bloated anonymous functions get:
services.Add(new ServiceDescriptor(
typeof(IMongoClient),
((Func<IServiceProvider, object>)((serviceProvider) => {
return new MongoClient("");
}))
));
Really all the signature information should be inferred such that I could instead write:
services.Add(new ServiceDescriptor(
typeof(IMongoClient),
(IServiceProvider serviceProvider) => {
return new MongoClient("");
}
));
Simplifying this syntax seems far more intuitive and for all I can tell, I'm not depriving the compiler of any type information (which is definitely not my intention here!). :)
You should be able to replace your entire anonymous function with _ => new MongoClient("")
AFAIK. Or if you're not a fan of the _
, serviceProvider => new MongoClient("")
.
@atrauzzi I believe the problem is that typeof(T)
is resolved simply as a Type
and doesn't influence generic type inference. It would be nice if the compiler could use typeof
expressions as a hint. I don't know about Scala but with Java I know that IMongoClient.class
produces a Class<IMongoClient>
which does affect generic type inference.
@HaloFour isn't there any proposal for this? if just Type
was generic.. that would be reflectiontastic.
@HaloFour -- I could be mistaken, but the point of interest in my snippet wouldn't be the typeof
, but the next parameter which is an anonymous function. It has to be of type Func<IServiceProvider, object>
according to the override for Add
.
The strongly typed declaration of that anonymous function offers everything needed to infer its -- hopefully I'm using this right -- "delegate type"?
@HaloFour -- Just tried out your suggestion and it produces the following error: Cannot convert lambda expression to type 'object' because it is not a delegate type
.
So if I understand my first snippet correctly, it casts the anonymous function/lambda to a specific delegate type. But based on everything I've provided in the implementation (and a little compiler magic of course), having to perform this cast strikes me as redundant.
@alrz Func<T, TResult>
only has one parameter, you may be thinking of Action<T1, T2>
.
@atrauzzi
Looking at the constructors for ServiceDescriptor
class in DependencyInjection I don't see one that directly corresponds to the sample code that you've provided. There is one that accepts a Type
, Func<IServiceProvider,object>
and ServiceLifetime
. I am capable of calling it just fine using a simple lambda:
var sd = new ServiceDescription(typeof(IMyService),
provider => new MyService(),
ServiceLifetime.Transient);
There also seem to be a bunch of generic helper static methods on ServiceDescription
.
@SolalPirelli Oh yes, you're right. He probably needs to use Transient
overloads.
@HaloFour -- I'm pretty sure the code I provided is exactly that syntax for one of ServiceDescriptor
's constructors.
Not sure what to say beyond that. The first snippet I list above seems to work, but attempting the simpler syntax you describe definitely gives me an error.
@alrz While Type<T>
might be useful in some circumstances it doesn't seem nearly as necessary as it is in Java as you can always do typeof(T)
within the generic class/method. Of the few places where it would provide an added benefit would be in a constructor of a generic class that has multiple generic type arguments where one of those arguments couldn't otherwise be inferred by the arguments to the constructor. Otherwise you wouldn't really gain anything over just specifying the generic type arguments directly.
@atrauzzi Don't know what to tell you, I'm looking at the code in the repo, which is potentially newer than what you might have downloaded. The ServiceDescription
class isn't generic so there is no generic type inference even in play here and the code that I've written compiles just fine. You might want to post to the issues of that repo as I'm quite sure that this is not related to any limitations of the compiler.
I was able to specify class literals as generic in Java in part because generics are translated by erasure, so no VM support was required. However, it leaves some uncomfortable gaps in their principal use cases, and the basic feature could have been done in Java without any language support.
The link to "Records / algebraic data types" in the opening post is wrong and points to "Pattern Matching"
@SoonDead This issue isn't really kept up to date (unfortunately, seems like the team is still working through how best to convey the best up-to-date status). That proposal does include records (not the link in the proposal, that's strictly pattern matching). ADTs are covered in a few other proposals like #6739, #5757 and probably a few others that I can't immediately find.
@SoonDead #206 describes both pattern-matching and records. The link is clearly labeled as pointing to a draft spec for pattern-matching only.
There is no mention of https://github.com/dotnet/coreclr/issues/2322 or Unmanaged generic type constraint + generic pointers, is there a reason for this? Does this actually require CLR changes? How can F# then already implement a "unmanaged" constraint?
@nietras F#'s unmanaged
constraint is not enforced by the CLR. Outside programs are free to use them with invalid type arguments.
@HaloFour thanks for your reply. Could you perhaps point to any material regarding the F# implementation? I presume this means it falls back to simple value type constraint? And perhaps an extra attribute only recognized by F#?
@nietras The first sentence begins "This is a list of features we have looked at for C# 7". That should help explain why dotnet/coreclr#2322 is not mentioned.
@MadsTorgersen Will there be any more design notes forthcoming? It's been many months since the community has had any updates on the shape of C# 7.0.
I'd really like to see Declaration Expressions make it back into the list. That was one of the features I was most excited about in C#6. Also to echo others, I would love to see an overhaul of XML comments. I think Markdown support would be a good alternative. It's easy to understand, human readable in it's non parsed form and would give formatting control to parsing tools.
@helmsb I'm not a fan of embedding any form of presentation directly into XML comments. It's relatively simple to take that XML and generate HTML or markdown or some other arbitrary presentation format, but once you start embedding the presentation format you're more or less stuck with that format.
I agree that XML comments are not particularly pleasant to read, or write (I don't think that javadoc or the like is any better). However I think that tooling improvements could make it a much better experience by rendering the XML docs into a nice format and perhaps providing a simpler editor so that the developer can avoid actually working with XML or any specific format.
On that note , with #7655 , it would be fantastic to be able to write markdown with compiler verification and auto completion.
Please consider to extend Linq to add a new keyword leftjoin or rightjoin. I'm sure a lot of .NET developers dream about this keyword when doing LEFT JOIN using SingleOrDefault() in conjuntion with select into.
By supporting this keyword you really bring Linq to a higher level.
@uyhung Can you please file your feature request as a separate issue, with a proposed mapping into API invocations or into the existing Linq operators? A comment on this issue won't be treated as a feature request.
Thanks @gafter, here it is https://github.com/dotnet/roslyn/issues/8710
Immutable types with included "with" method/keyword for "changing" stuff and build-in equals/hash would be extremely nice.
As I understand it, the class Type is obsolete and superseded by TypeInfo, so what about a typeInfoOf(x) operator also so we do not have to use typeof(x).GetTypeInfo() ?
As I understand it, the class Type is obsolete and superseded by TypeInfo, so what about a typeInfoOf(x) operator also so we do not have to use typeof(x).GetTypeInfo() ?
Type
is not superseded, but its scope has been greatly reduced. TypeInfo
is the new API for reflection on a type, and Type
is just a lightweight reference to a type. A typeInfoOf
operator couldn't be added because it would require a dependency on System.Reflection
, which is now an optional dependency.
The thing I really hope to see one day is the support for the concept of Aggregate in C#. Currently, the concept of nested classes allows us to do the opposite of Aggregation (nested classes can access the private members of the enclosing class), while what very useful is to introduce a new accessibility keyword so that an aggregate can access the private members of its children (nested class)
`
public class Aggregate
{
public string AggregateProp {get; set;}
public void Do()
{
ManagedClass obj = new ManagedClass();
obj.DoIt();
}
aggregated class ManagedClass
{
public string Name {get; set;}
private void DoIt()
{
}
}
}
`
The aggregated
keyword would be invalid when not used in the context of a nested class. I can't think of a backward comptability issue, and since there's already the notion that nested classes can access private members of the enclosing class, I think this addition wouldn't be awkward and would add a lot to the expressiveness of the language.
@JoeyFR
You should create new issues for any specific proposals, otherwise it will not be tracked.
The specific ability of a nested class being able to access the private members of its parent is baked into the CLR. To allow for any class to access the private members of any other class other than in that specific scenario would require CLR changes. Is there a design reason to need or want this kind of functionality that doesn't violate the nested type design guidelines?
@HaloFour Sorry about that, thanks for letting me know I'll create issues moving forward.
Interesting, I never came accross this page to be honest with you. The scenario I had in mind clearly violates some of these guidelines.
In terms of design it was essentially to be able to express the aggregate relationships of domain objects. But reading the guidelines you sent, this is clearly off the intended usage of nested classes. The CLR limitation also puts the whole thing under a different perspective. I'll rethink this proposal.
Just wondering if it is possible in C# to replace logical operators &&, ||, ! with and, or, not respectively
It will improve code readability a lot.
if ( temperature > 98 and temperature < 105 or pressure == 780 )
{
}
@nirvinm
@nirvinm following your thought, add "then" and replace curly braces with "begin" and "end" and you'll will have vb.net syntax.
@nirvinm On vb.net "and" and "or" are not "short circuited", due to legacy vb6 code ported to vb.net. For that vb.net has additional "AndAlso" and "OrElse"
Just wondering if it is possible in C# to replace logical operators &&, ||, ! with and, or, not respectively
It will improve code readability a lot.
No, no it would not. It would on serve to help those who cannot read the code to kind of better misunderstand the code. It would make writing the code significantly more painful and only serve to remove more legitimate names by stealing them for keywords.
AND
&&
does not mean "and" it means "test the next condition only if the prior condition was true, then use the next conditions result as the combined result, otherwise result in false" and that's one hell of a keyword.
||
is similar to &&
.
!
does mean "not" in some cases, it means "logically negate" in all. Do you really want your code reading like this: if (logical_negate foo.IsAnnoying)
?
@whoisj Why can't 'and' do short circuiting as &&. Though && is more symbolic than 'and', both do the same thing.
As @HaloFour said, this is #6212 all over again. while C++ does feature a complete set of alternative operators, that's not because of expressiveness issue and yet the reason is not applicable to C#.
See http://en.cppreference.com/w/cpp/language/operator_alternative
Why can't 'and' do short circuiting as &&. Though && is more symbolic than 'and', both do the same thing.
Because &
means "and", without the short-circuit. And, not short-circuiting is sometimes necessary.
Same goes for |
meaning "or" without the short-circuit.
Hello Everyone
What do you think about multi chek feature for C#
Smth like this:
``
enum Math{
One, Two, Three, Four
}
Math someVar;
void DoSmth(Math someVar){
if(someVar = Math.One || Math.Two || Math.Three)
return;
//some logic...
}
@Symfony2 #8533, #6235
Why is #161 (Destructible Type) in both "Some Interest" and "Probably Never" buckets?
We would like to solve the problem in C#, and pick over this proposal for ideas, but we'd need to noodle with it to make it a better fit. It would need to integrate better with current IDisposable.
Do you really want your code reading like this: if (logical_negate foo.IsAnnoying)?
@whoisj I absolutely do. I already write all negative if statements as if(false == foo.IsAnnoying)
using the ! operator inside of a logic statement is just absurdly easy to overlook or accidentally delete without any cognizance that you entirely changed the logical result.
IEnumerable<something>
shorthandI would really like to see a shorthand for IEnumerable<something>
in Parameter and variable declarations.
I think, something<>
would be nice.
this would
something<>
would be _like_ a something[]
, meaning there are multiple something
s there that can be iterated Furthermore, nesting would be possible using IEnumerable<IEnumerable<something>>
=> something<<>>
(which I prefer to something<><>
which on the other Hand would be analog to something[][]
, actually...).
And with the something?
postfix to represent Nullable<something>
there is already a precedence.
As far as I know, _GenericType_<>
(an unbound generic type) is not allowed in return type, Parameter or variable declarations, so the conflict with the Type isn't really there.
So far the only thing I found as to this idea was a deleted stackoverflow discussion from 2009, this one:
[http://www.stackprinter.com/export?service=stackoverflow&question=794369]
@AdmiralSnyder
I like this suggestion, however, to be not confused with open generics I'd prefer T{}
for IEnumerable<T>
and {TKey: TValue}
for IDictionary<TKey, TValue>
as long as it's not ambiguous, and it could play nice with #6949 literals.
FYI, we've just updated this worklist of C# 7 language features with our current thinking.
@gafter
I see that nullability tracking has been removed from the list. Is it definitely dead?
@gafter Nice. Very curious to see how pattern matching, records and tuples shake out towards the C# 7.0 release.
One suggestion, would it be too much to have a Wiki page with a table of considered features with links to proposals and issues and a category as to how much interest there is in the feature as well as a guestimate as to where it might fall in the language roadmap? Trying to keep track of proposals mixed in with these issues has been cumbersome and I think that might be why dupes are common, even for issues that aren't closed. The CodePlex site had a Language Features Status page which somewhat served this purpose and it was nice to have one place to quickly glance. I can understand not wanting to give the false impression of promising any specific features, though.
@gafter what happened to non-nullable reference types?
Thanks for the update. I'm excited that "generators" are being considered for C# 7.0. Previously there were indications this wouldn't happen for several more versions of the language. I believe getting it in sooner is a better decision because it has the potential to be a very high-impact feature.
One comment- I think generators are not a very good name for this feature given they have a completely different meaning in JavaScript and other languages.
It looks like the IAsyncEnumerable is deferred as well. Though this feature would be useful I agree it makes sense to push it back given more immediately compelling features for C# 7.0.
but not including algebraic data types
Too bad this one is going away too. While pattern matching helps in common scenarios like if(o is T t)
I think an important use case for match
is deconstructing ADTs. It would be nice to dedicate next version to functional programming style, immutability and pattern matching and consider related features that could be more powerful together for C# vnext.
@alrz I'll make the wild assumption that it's more a matter of which features they think they can accomplish in the C# 7.0 time frame and that pattern matching et al. will be metered out over several releases, including ADTs.
@HaloFour I don't really care for any of the features that currently mentioned in the "some interest" bucket, not that they woudn't be useful at all, they just seem to be very diverse and unrelated. I'd rather have a near complete set of features around functional programming style at my disposal so it can directly affect my coding paradigm. Following a "theme" could be really advantageous if you look at it this way ("generators" here are an exception though). Other aspects to improve could be better type inference, more powerful async (including async sequences), sole syntactic sugars, etc that perhaps would have a lower priority because you can already get by without them.
@benhongh No, non-nullable reference types are not dead. They are actively being worked on. They simply won't be done in time for C# 7. We need a lot of experience with a prototype to make sure we have the right shape of the feature.
@alrz I agree regarding algebraic data types. This is the current thinking but it is subject to change. Part of the problem is that we are over-committed. If ADTs don't make C# 7 I expect lots of people will ask for them and we'll do them in C# 8.
@gafter Yes that is understandable, but just to say, it's not like that ADTs are something somehow irrelevant, I'd say they are part of the the whole pattern-matching capability and for the sake of completeness (pun intended) they should be considered at the same time — I wish.
By the way, I'm happy to see non-nullable reference types are postponed because IMO the proposed implementation was not satisfying at all. Perhaps F# strategy could work...
Perhaps F# strategy could work...
@alrz did you mean writing a whole new programming language? :wink:
What happens to Event Initializes? They disappeared although they were described as planned features in C# 6.0 in many posts ...
C#
var obj = new Obj()
{
Notify += handler;
}
@alrz non-nullable reference types are under active development for a release _after_ C# 7.
@icylogic Event Initializers didn't make the cut. The scissors are still sharp and we may need to cut more.
any plans to improve inner subs / functions ?
Dim s1 = Sub() s1()
now have to write
Dim s1 As Action = Sub() s1()
@vbcodec #3990 — _Mind the scissors._
Removing
private protected
(Proposal: #1384)per @jaredpar
Hi. what exatcly now happens to algebraic datatypes. The last 2 weeks I had many issues on our framework that put a high demand on the possibiliyt to have generic algebraic datatypes. Also the need to allow pointers on these. Otherwise C# seems to be to slow to process large datasets.
@msedi with regard to pointers this is possible using the Unsafe
class discussed in https://github.com/dotnet/corefx/issues/5474 and which is available in a nuget package as https://www.nuget.org/packages/DotNetCross.Memory.Unsafe/ The performance for some compounded value types is, though, rather poor see https://github.com/dotnet/coreclr/issues/3539
Removing
- Records (Proposal: #206), including
with
expressions (Proposal: #5172)
- algebraic data types
- More betterness (generic constraints, static vs instance) (Proposal: #250)
- params IEnumerable / varargs (Proposal #36 and #37)
- utf8 string literals (Prototype at https://github.com/VSadov/roslyn/tree/utf8)
- const var (Proposal: #4423, Prototype: #5050)
See https://github.com/dotnet/roslyn/blob/master/docs/Language%20Feature%20Status.md for the compiler team status.
(Missing from that doc is a pointer to the records branch where its spec is found)
@gafter
Don't run with those scissors. Kind of a shame to see records pushed but it would probably make more sense in the context of ADTs and DUs.
Awesome to see the language status page. Anyone know any github tricks for receiving notifications when a file is modified?
Super disappointed that records are being pushed. They are by far the highest value-add feature in my day-to-day vs anything else proposed for C# 7.0
@gafter Looking at that status page, I'd say you should be crowned the undisputed LDM champ. 8 features spearheaded by you!
I think there's no reason to support match expression (and therefore throw expression) when we don't have ADTs and/or completeness. If C# 7.0 is dedicated to "pattern matching" I expect to see far more sophisticated capabilities in this area, because if(o is T t)
+ tuples can't be called "pattern matching", really.
@alrz
If C# 7.0 is dedicated to "pattern matching"
You'd rather them push the entirety of pattern matching? If the team intends to move to a faster release cycle I think it makes sense for large features (like pattern matching) to be tackled iteratively. Operator is
appears to still be on the table so the matching functionality of records remains in place, there just isn't a good/concise way to describe them. I'd rather not wait 3+ years for C# 7.0 to be "satisfactory" to a F# developer :)
You'd rather them push the entirety of pattern matching? ... I'd rather not wait 3+ years for C# 7.0 to be "satisfactory" to a F# developer
@HaloFour You mean an early match expression can make C# satisfactory to a F# developer? I'm not expecting anything more than F# patterns though. We are still 3+ years behind of F# features anyway. Faster release cycle doesn't mean that we will get there sooner.
By the way, record decomposition can be implemented via code generators, for example:
[Record]
partial class Student {
public string Name { get; }
public decimal Gpa { get; }
}
// to be generated
partial class Student : IEquitable<Student> {
public Student(string Name, decimal Gpa)
{ this.Name = Name; this.Gpa = Gpa; }
public static void operator is(Student self, out string Name, out decimal Gpa)
{ Name = self.Name; Gpa = self.Gpa; }
// etc
}
// tada
if (s is Student("Name", *))
A little more unpleasant generator can be used to generate ADTs' boilerplate. But since you woudn't have completeness you'd better to wait. Huh.
Good removing of features.
Records really had no added value. We do not have to declare new data structure every 10 or even 100 lines of code. Classes and structures are enough for these tasks. Additionally, auto generated code may be unwanted for some cases.
For pattern mathing, remove is
operator and positional matching with wildcards. These things really create 'dark magic', and are practically limited to comparisions using enums / bitfields. Simple casting if(o is T t)
is most clear and usefull out of this feature. This way name 'pattern matching' should be changed to 'types matching'.
Instead drilling down in difficult topics with low potential to improve, take a look for other fields like #5445 (#8670).
For tuples, I am bit disappointed that they are limited only to structs. Take a look at my proposal #9924, where I have suggestions how to avoid this limitation, and also 'unlock' anonymous types from functions where they are defined.
Update Language Feature Status page with original / replace feature.
Hello Everyone!
What do you think about syntactic sugar for simple data types like arrays, set, dictionaries, like this:
C#
var array_of_int = new [int] [1, 2, 3, 4];
var set = new [int] {1, 2, 3, 4};
var dict = new [string, object] { "a": new object() }
@zapic
I don't think that the Swift array syntax makes much sense in C# where there already is a notation to define the type.
The following syntax is already valid for arrays:
var array_of_int = new [] { 1, 2, 3, 4 };
So I don't think it makes sense to add a new notation for arrays and then have the same notation construct sets. A literal format for lists and dictionaries would be nice, but with collection initializers it doesn't add _that_ much to the language.
@alrz
It may be that C#/VB with code generators may end up as C++ with macros. There will be lower pressure to add new and complex features, because devs can write pseudo-code, and generators will do rest.
We do not have consensus in the LDM that we should support recursive patterns (i.e. user-defined operator is
). We'll see what feedback we get from a prototype.
@gafter recursive patterns lose a lot of their value if records are out of scope.
@gafter
We do not have consensus in the LDM that we should support recursive patterns
Now I think you guys are just trying to intentionally torpedo pattern matching.
recursive patterns lose a lot of their value if records are out of scope.
I don't disagree, and maybe it's worth holding off specifically on the operator until considerations can be made as to how well it works with records/ADTs/DUs. But if that's the case I think I'd rather see all of pattern matching pushed until those stories could be resolved. Does type switching by itself really bring enough value?
@gafter Perhaps its time for you guys to consider shipping language updates independently from VS versions, like TypeScript and F# already do. The TS team is shipping new features every few months and it seems to have worked out really well for them. That way you can ship all the features when your team is actually ready and not rush for whatever arbitrary date is planned for VS 2016.
VARIADIC TEMPLATES. For the expressivity of some concepts that are in c# for a long time but are implemented in a "fake" way with "Generic Classes Overload" like func, action, predicate, tuple...
@MarcosRapoport #5058
@MgSam but you can still get any Roslyn version, compile it, place it withing project as references libraries as we have right now for C#6 for VS2013 support. The only missing thing is VS integration, intellisense and other related things.... but in the code you can use it right now
@sergey-litvinov Just because you can download it from Github and compile it doesn't mean it's ok to use in production code. Unless it's an official release supported by Microsoft, it's not suitable for use in production code.
Kind of disappointed most proposals around extension methods etc. didn't make the cut.
Though looks like #165 (Allow by-ref Extension methods) might have.
Removing
- Pattern matching (Proposal: #206, also Patterns Spec), including
- let statement
- match expression
- throw expression
and replacing with
- Typeswitch (subset of Proposal: #206 Pattern Matching)
Ouch. I can totally understand wanting to bake those concepts a lot more before you try to ship something, especially where there is still uncertainty. Big question, is the compiler/VS integration at the point where you could ship features of such a caliber as point releases or does this effectively mean that C# won't see pattern matching until at least 2017?
We do expect to have "point releases" of the languages in the future, but there are disadvantages to making too frequent language changes.
Is there any place or discussion that discuss the removal of these features from pattern matching? if not can someone please elaborate farther on the reason for their removal?
@eyalsk The features have not been "removed from pattern-matching". They've been removed from our plans for a particular release of the language. The reason is that the LDM's work on the design (even reviewing the existing design) was not far enough along to complete the development of the feature in the C# 7 timeframe.
@gafter thanks for the clarification.
WHEN will C# feature multiple inheritance?! at version 15?
@HIETE yes, sure. In C# codename "15"
@HIETE Multiple inheritance can be a very dangerous thing and lead to really bad design. I've had to debug Java code with multiple inheritance that still gives me nightmares.
@helmsb But single inheritance produces an other inconvenience. For example, when you adopt MVVM, you often need a BindableBase class to help you implement IPropertyChanged. Sometimes you also need a Disposable class to help you implement IDisposable pattern. But when you want a class implements that two interfaces... Sorry, you must abandon one inheritance and repeat yourself to implement the other interface.
Single inheritance limits the abilities of code reusing and combination.
@sunnycase I think that you'd get more out of traits/mixins than multiple inheritance. See #60.
@HaloFour But a mixin cannot give you the ability to access protected members.
@sunnycase Generators also fit the bill. Using a base class to derive multiple tiny pieces of logic, especially just helpers, seems entirely inappropriate.
Aside that, the CLR was designed entirely around single inheritance, and very intentionally so. It would require quite the overhaul to change that. That's even assuming that the argument for/against multiple inheritance is substantially different than it was 16-17 years ago and there is a reason to try to plod forward, which I doubt is the case.
If we believe that inheritance should only be used for "is-a" relationships, then BindableBase
and Disposable
are not good candidates for base classes. A dog is-animal, not is-a bindable.
You're looking for mixins.
there is no use case whatsoever for multi-inheritance that isn't an antipattern. it is something you don't want in the language.
you should use a dedicated, single-responsible, object for each behavior and put the logic there.
C# does allow multiple inheritance but just for interfaces. Default methods (#258) would enable you to reuse a common behavior among multiple derived classes without falling back to mixins.
@HaloFour
A generator is good, but each class will generate it's own implementation, it makes the binary larger.
@JayBazuzi
Mixin is not sutable for BindableBase, because it contains protected members.
@alrz
An interface is always public or internal, sometimes you just want protected logics.
@sunnycase Can you provide some examples because I can't see how a BindableClass nor a Disposable class is useful especially a Disposable class, I mean there's a reason it's called a pattern and it's generally used when wrapping unmanaged resources.
I never understood the need to abstract the mechanism for IPropertyChanged, _maybe_ someone need to fix the wording for the DRY/DIE principle so people will stop create abstractions to every piece of code.
I understand you want to use inheritance for reusability but it doesn't make sense in C++ and it wouldn't make sense for C#, however, C++ offers access specifiers to solve this and instead of using public inheritance one can use protected or private inheritance but even then if you will ask Scott Meyers or Herb Sutter what they think about multiple inheritance (MI) they will tell you to reconsider unless you know that there's absolutely no other way to design the thing differently to be as elegant and/or efficient without it.
I'm not sure what it takes to add access specifiers to C# but my guess is that it's going to be ugly but besides that adding MI to C# will also add a bunch of other problems that exists in languages that support MI and then there will be a need for even more features to solve these problems.
:+1: mixins or straight up full fledged macro support
:-1: multiple inheritance
Why was Slicing (#120) removed?
It was removed to let people know that it won't make C# 7. All our compiler developers are fully engaged on other features.
@gafter
Do you plan to implement #6671 ? It may be very helpful for code generators (#5561)
@vbcodec #6671 is not planned for C# 7.
@andre-ss6
The CLR wasn't able to get slicing completed in the time frame for C# 7.0 hence it fell off our plans.
This is a feature that is actually much more about the runtime than the compiler.There are a number of possible designs for slice, some of which do put more burden on the language. But even in the worst case the language work is small. The runtime cost dwarfs the compiler in every case.
Can we please have a shortcut for case insensitive string comparison?
"a" == "A" (
String.Equals("a", "A", StringComparison.OrdinalIgnoreCase)
Personally, I use the latter all the time (and should have been default in my opinion).
Something like:
"a" ~ "A"
"a" === "A"
or whatever.
Probably just a compiler thing even.
@jihohan There is zero chance of this happening, so I suggest making an extension method if you really need to reduce your typing.
``` C#
public static bool Eq(this string a, string b)
{
return String.Equals(a, b, StringComparison.OrdinalIgnoreCase);
}
"A".eq("a") //true
```
@jihohan More accurately, this is something for the framework, not for the compiler. See dotnet/corefx#649 which could make it in.
@MgSam I've done extensions before but it feels a bit clunky to me, doesn't convey the intention as much and if you try, then you are back at square one, creating longer method names.
@Joe4evr I'm glad I'm not the only one who finds this annoying and apparently some of the bigger names in the industry is feeling it as well. EqualsIgnoreCase is definitely an improvement but it's too long and it does not distinguish between OrdinalIgnoreCase vs CurrentCultureIgnoreCase vs InvariantCultureIgnoreCase. Sheesh!
So talking about 80-90% case, what do I usually use OrdinalIgnoreCase for? Key Comparison. You don't care about case and you want byte by byte comparison.
In the past, I've created extension methods as @MgSam has suggested and created a method called KeyEquals(). I'm just not a fan of the name. Perhaps EqualsCanonical?
I still vote for an operator.
And I don't understand why it would be a framework thing vs compiler thing - it can be just a syntactic sugar.
Otherwise, regular expression idea sounds good too. Something like:
if ("aBc"./ABC/oi) { Debug.Print("true"); }
Internally that could translate to String.Equals("aBc", "ABC", StringComparison.OrdinalIgnoreCase).
But that's an instance method. What I really want is a direct replacement for String.Equals(x, y, StringComparison.OrdinalIgnoreCase) which still works when either x or y is null.
@jihohan can't it be an attribute? I mean maybe we can set an attribute on assembly/class/method level to allow the default equality to change its behaviour and continue to use the regular equality operator.
I don't know if it's feasible, I didn't think this through but it's just an idea.
EDIT: I take this back, this isn't really a solution but moving the problem, more like hiding it which is even worst.
VB has this feature with "Options Compare Text" but I have been bit more than once with Dictionaries ignoring this option.
Providing C# syntax for functional concepts (e.g. adding matching within the switch syntax) may make it more approachable for C# programmers, but you should also provide alternative functional syntax for those readily embracing functional concepts.
@cowsen can you provide some examples? what alternatives are you looking for?
Eyal,
Thanks for your quick response. Some simple examples from F#:
let foo x =
match x with
| 1 -> "one"
| _ -> "not one"
Or even more terse in a lambda expression:
List.map (fun x -> match x with | 1 -> "one" | _ -> "not one") [0;1;2;3;1]
I initially started programming in VBA, but when .net came out, I embraced C# because of its C like syntax, which is quickly becoming the de facto standard in OOP (e.g. C++, Java, Javascript, C#, Swift). As C# embraces functional concepts, it should also embrace functional syntax, at least as an alternative to C# friendly syntax. We started embracing functional syntax in C# 6.0. Visual Basic is a very user friendly language, but modern developers are willing to sacrifice a little readability for concise, terse code. I really like F#, but it is unlikely that it will cross the chasm into mainstream applications. However, its legacy can be that many of its functional concepts AND syntax was absorbed into C#.
Craig Owsen MBA, CPA
Senior Manager, Financial Applications
Concentra
972-725-6494 (o) | 972-364-8224 (f)
5080 Spectrum Drive
Suite 500
Dallas, Texas 75001
Craig.[email protected]
From: Eyal Solnik [mailto:[email protected]]
Sent: Wednesday, May 18, 2016 11:51 PM
To: dotnet/roslyn
Cc: Owsen, Craig; Mention
Subject: Re: [dotnet/roslyn] C# 7 Work List of Features (#2136)
@cowsenhttps://github.com/cowsen can you provide some examples? what alternatives are you looking for?
—
You are receiving this because you were mentioned.
Reply to this email directly or view it on GitHubhttps://github.com/dotnet/roslyn/issues/2136#issuecomment-220226979
The information transmitted is intended only for the person or entity to which it is addressed and may contain CONFIDENTIAL material. If you receive this material/information in error, please contact the sender and delete or destroy the material/information.
@cowsen
I'd suggest looking at the pattern matching proposal here:
https://github.com/dotnet/roslyn/blob/features/patterns/docs/features/patterns.md
This proposal does include syntax for an expression form of match
which would function similarly to that in F#:
object obj = ...;
var result = match obj (
case int i: i.ToString(),
case string s: s,
case *: "uh oh"
);
The exact syntax is still under consideration and like most of the pattern matching spec this won't make it into C# 7.0.
Thank you for your quick response. The attached snipped is more of a hybrid. I think C# would be better server with alternate syntaxes: C# friendly and functional friendly. We have alternate syntaxes for LINQ.
Which is more terse?
“case” => 4 keystrokes
“|” => 1 keystroke
But, much more importantly is consistency across languages. I was able to quickly pickup Javascript because of similar constructs AND syntax to C#. I have been exposed to just F#, but you have the opportunity to survey all the major functional languages to look for commonality before settling on a functional syntax. I am confident you will release a great C# syntax, but we will have to eventually provide a functional syntax to be taken seriously by functional developers.
Craig Owsen MBA, CPA
Senior Manager, Financial Applications
Concentra
972-725-6494 (o) | 972-364-8224 (f)
5080 Spectrum Drive
Suite 500
Dallas, Texas 75001
Craig.[email protected]
From: HaloFour [mailto:[email protected]]
Sent: Thursday, May 19, 2016 8:29 AM
To: dotnet/roslyn
Cc: Owsen, Craig; Mention
Subject: Re: [dotnet/roslyn] C# 7 Work List of Features (#2136)
@cowsenhttps://github.com/cowsen
I'd suggest looking at the pattern matching proposal here:
https://github.com/dotnet/roslyn/blob/features/patterns/docs/features/patterns.md
This proposal does include syntax for an expression form of match which would function similarly to that in F#:
object obj = ...;
var result = match obj (
case int i: i.ToString(),
case string s: s,
case *: "uh oh"
);
The exact syntax is still under consideration and like most of the pattern matching spec this won't make it into C# 7.0.
—
You are receiving this because you were mentioned.
Reply to this email directly or view it on GitHubhttps://github.com/dotnet/roslyn/issues/2136#issuecomment-220323814
The information transmitted is intended only for the person or entity to which it is addressed and may contain CONFIDENTIAL material. If you receive this material/information in error, please contact the sender and delete or destroy the material/information.
I've made some simple extension methods to simulate pattern matching.
PatternMatchingExtension
Like this
"foo"
.Match<int>(x => Console.WriteLine($"int {x}"))
.Match<string>(x => Console.WriteLine($"string {x}"))
.Match<_>(x => Console.WriteLine($"object {x}"))
;
new { a = 1, b = 2 }
.Match<string, int>((x1, x2) => Console.WriteLine($"<string, int> {x1} {x2}"))
.Match<int, int>((x1, x2) => Console.WriteLine($"<int, int> {x1} {x2}"))
;
var len = new Function<IList<int>, int>()
.Match(list => list.IsEmpty(), self => list => 0)
.Match(list => true, self => list => list.Match((x, xs) => self.Invoke(xs) + 1))
.ToFunc()
;
len(new List<int> { 1, 2, 3, 4, 5 }).Println();
var fib = new Function<int, int>()
.Match(x => x == 0, self => x => 0)
.Match(x => x == 1, self => x => 1)
.Match(x => x > 1, self => x => self.Invoke(x - 1) + self.Invoke(x - 2))
.Match(_ => true, self => _ => { throw new ArgumentOutOfRangeException(nameof(_)); })
.ToFunc()
;
$"fib(10) = {fib(10)}".Println();
@YangFan789 that is really really really cool
Did anyone request ability of using yield return in local functions/anonymous delegates finally?
@pmunin Local functions can be iterators, see #3911.
I'm disappointed that #262 is not included in the list for C# 7 (Generic Enum Constraints). Another year, another new version of the language, and this feature (requested since 2009) is still disregarded.
How about C# properties extensions? Like method extensions, but for properties
@pmunin Extension everything, #11159, which is most likely post-C# 7.
@Ultrahead thankfully that can be achieved by using https://github.com/jskeet/unconstrained-melody (or the IL directly yourself)
@dotnetchris thanks for posting that solution!
I hope someday we have this feature directly available for C# given that, afaik, F# do already handle Enum constraints.
I'd like C# to return nullable value in when using the conditional operator with a struct and null:
var nullableInteger = condition ? 1 : null; // instead of:
var nullableInteger = condition ? 1 : default(int?); // or:
var nullableInteger = condition ? (int?)1 : null;
I know a _struct_ cannot be cast to null or the other way around. But C# is aware of nullables anyway, and there's nothing else I could _possibly_ mean by this code.
I would to have C# 7.0 to catch multiple exception's like below.
{
}
catch(FormatException || OverflowException ex)
{
}
C# 6.0
catch(Exception ex) when (ex is FormatException || ex is OverflowException ex)
{
}
@deepumi it's better to write a small proposal about it than making a comment about it.
@eyalsk Where would I submit such a proposal?
@realbart on github, create an issue with the name "Proposal: Something" and write whatever you like.
@realbart I think that someone just beat you to it! #11886.
@eyalsk Thank you, created proposal #11889
Guys, speaking here on behalf of the startup community and modern mobile generation (multi-time founder/entrepreneur in Toronto).
We are one of the few startups around that run .NET as our back-end, and we do this because of the belief of C# as a language and the .NET stack in terms of both professionalism/scaling while also development speed and all the strongly-typed achievements in the entire ecosystem. We run Swift, Kotlin and C# on native iOS/Android and ASP.NET MVC/Core as our stacks.
HOWEVER, I can say from the transition into Swift and Kotlin as the primary languages that we do all our mobile development in, nullability is the single biggest thing that has happened in the programming world this decade (right after the C# 'async'/'await' which C# has so elegantly brought and is continuing to bring to the world).
GIVING UP ON NULLABILITY FOR THE C#7 SHOULD IS SIMPLY NOT A FEASIBLE OPTION
Making backwards support baggage tradeoffs such as the proposed "Object!" syntax IS ALSO NOT ACCEPTABLE. If you need to introduce a new keyword (ie: "nullaware") at the top of every C#7 file to mark the file to the compiler as converted to C#7 then so be it. But you simply can't make baggage-based trade-offs and prevent or limit the effectiveness of crossing the nullabilty chasm which C# sits squarely on the "old world" side of.
Both Swift and Kotlin have figured out how to cross the chasm and it has taken them several years to do so (annotating old non-nullability-aware libraries, changing how construction/inheritance works, updating framework paradigms etc.). For C# to not tackle this means the .NET ecosystem is a whole generation behind by several years. Microsoft frankly cannot afford to lose any more years in winning over developers to pick up .NET as a platform. Let's not even begin to mention the design language and UX limitations which Windows and the Metro design language (yes we should still be calling it that) has imposed – and that because of it you don't have a chance in hell of convincing a modern, mobile developer to give Windows a chance against OS X. This will ensure developer churn from Windows to Mac will continue to happen and that new devs will not bulid up their careers on Windows, since I'm sure a design language fix is not going to come soon (Microsoft afterall does not have design in their DNA at the executive level of the company). The only other alternative left is for .NET to become dominant cross-platform – THE strategy which Microsoft is currently executing all-in on.
This means that for the .NET transition to cross-platform (read: OS X) and for the Xamarin bet to pay off, C#/.NET/Xamarin MUST be able to present comparable languages/ecosystems to the modern alternatives. DESPITE Xamarin having been acquired and made free (this was a crucial step), we as a startup community simply cannot make the call to move to a development ecosytem that is not built on nullabilty while still taking the hit of the MANY real-life limitations Xamarin structurally has (3rd party library mapping/adoption, second-class IDE, non-native design tools – ie: lack of integration with Android Studio / Xcode / AppCode).
I know I'm throwing a lot into the mix here, but I really think to execute on the current Microsoft strategy of saving .NET from dying along with Windows (I'm not overplaying a single thing here), C# needs to play its part into becoming a VIABLE alternative for native, modern development on Mac on both the mobile and back-end fronts. The C# team's part in doing this is moving C# over to the nullable world and showcasing the other big benefits of C# to OS X and dynamic language developers (Ruby/Python/JS/Express). Your goal/mission in this CANNOT be misunderstood. You are playing a generational / life-saving role for Microsoft at a crucial part in Microsoft history where Windows has failed on mobile, has failed on the consumer front and it's only hopes of regaining success are in re-invention on the Mac platform and winning over developers from there until Windows evolves from a design and consumer perspective (perhaps windows "12" / 2020 time-frame?)
Do NOT scope nullability out of the C#7 time-frame. Push the release date back if you need to... and please guys: let go of the baggage in the language design decisions around the critical feature. C# needs to win. It needs to bring over the generation of developers against the current native alternatives of Swift, Kotlin and JavaScript which are making strides in extremely fast pace. You DON'T have another C# language generation to fix this. If Swift becomes a viable platform for sever-side development and you lose the .NET web/server-side battle as well.... the current execution of the Microsoft saving strategy will literally be doomed. Again, I cannot understate the importance of doing this. Swift and Kotlin/Android are not standing still. Cross waiting for C#8 timeframe off your guys list of luxuries. You do not have it.
.
With all love and respect.
Marcel Bradea, CTO
Happ – http://happ.rocks
If the design team listened to every group demanding that the release be postponed until their feature of choice was implemented we might finally be seeing C# 7.0 when Hurd hits 1.0. In the case of non-nullability I don't think that the team pushed back due to priorities but rather because of the amount of design work still necessary.
Guys, speaking here on behalf of the startup community and modern mobile generation (multi-time founder/entrepreneur in Toronto).
You are not speaking on behalf of anyone but yourself.
I'm going to be blunt, because you need it: if you genuinely believe any of the opinions expressed in your rant, you need to get your head out of the bubble you're in. You clearly have no clue how the world works outside of buzzword-filled startups.
Hey @SolalPirelli I don't want to pull the conversation into any rant-based or opinion-based conversations. I actually come from the enterprise world, consultancies, and am x-RIM and x-Google, while also founding 2 startups and being an executive heading up product on a third. None of that is important, and this forum is probably not the right place to have the high-level strategy discussion – but I placed it here in light of having a better access to the team making the prioritization decisions.
The "opinions" above are simply my analysis of the industry and of seeing what developers in both startup and enterprise get attracted to. .NET is nowhere in the startup world and Microsoft HAS failed on the consumer front (Windows Mobile officially pulled out, Window Metro is a fail – nevermind that Windows 10 had great adoption on the desktop side). I have seen many competent teams that simply cannot produce a good app in the Windows design language. Take a look at Trello who both tried very hard (design blogs, early releases etc. while also being highly competent as a team). I am a past designer as well and I've seen what it means for design to be in the DNA of founding/executive teams. It's very different than when it's not. It's not trivial to describe to engineers how the Windows design limitations can have this impact upon the apps designed for it – but they really do and has been an enormous contributor to Windows failing in the consumer world.
I strongly believe getting a foodhold in the Mac world (where current center of innovation for development _in North America_ lives – and has now for many years) and I think Satya Nadella understands this very well. The cross-platforming of .NET and the amount of weight all the MS teams are placing on this sit upon this premise.
When stacked against Swift and Kotlin, the current leading langs/ecosystems for modern development, I am simply pointing out that losing another generation (ie: years) by having C# be null-unaware is not going to position C#/.NET/Xamarin strongly enough to give developers reason to adopt it over the native alternatives. And I think that winning over startups / new innovation is critical for MS to turn around the churn and regain significance for the next wave of products/startups/developers.
Thus I am stating my strong opposition to the de-prioritization of this feature for C#7 at an executive/strategic level for the C# team. Feel free to DM me or reply privately if you think my analysis is off on any of its premises. I don't want to deviate the important discussions at play here with personal rants. My sincere apologies if that's how the analysis came off.
@marchy
It's not worth devolving this into some kind of pissing match over who has the most synergy or other inane irrelevant crap like that. Microsoft is taking their time. They have put several proposals forward and favor changing the default behavior of the language as you have described. They just want to get it right the first time as they prefer to not still be making breaking changes to the language three major versions in. I applaud them for being so deliberate.
Thanks @HaloFour for your applause to the C# team. You guys have been amazing and achieved huge things to date.
I also want the team to win and am a constant voice for C#/.NET in the startup ecosystem here in TO because I believe in the vision and benefits of .NET as a whole.
Despite running .NET on the back-end and Xamarin becoming free however, our new company did the analysis and we have chosen Swift and Kotlin as the technologies to build out our mobile offerings upon. And being .NET guys – that is a huge problem. If WE can't be won over... how are people unfamiliar with the benefits going to even consider it?
My point is the market isn't forgiving, and it doesn't wait around. I was at RIM (and left) the year after the iPhone was launched. The importance of .NET winning on the Mac is no less than an existential problem for Microsoft, and I want them to win because I firmly believe the _technology stack_ is the better one. Let's hope this is just temporal fears and the ship can indeed be turned around. But we are literally one or two moves away (let's say Google announcing Swift as a natively-adopted language for Android, and a competent company building out a Swift-based back-end/server, which the open-sourcing of Swift has opened the possibility to and already have the first contenders ie: Perfect) before the cross-platform .NET dream could be shattered to pieces. There is only so long you can tread in the hopes of the lack of better alternatives before those alternatives actually come to reality – and then suddenly it's too late.
Good luck team, and thank you for bringing in the community in your design process so we can share in on these crucial discussions. We all want .NET to win. And to the team execs making the final calls on the decisions: _make taking nullability off the table a non-option for the team_. The market price is simply too great.
I agree with @marchy fixing the billion dollar mistake really needs to be sent back to the top of the lists for C#7.
@marchy The whole idea of one technology winning over the other seems really odd to me, I really don't understand it and I really don't think that the price is too great, however, it can be, if they will get it wrong!
@dotnetchris It's not about sending something to the top of the list, it's not like they wake up in one shiny morning and telling themselves, let's put this first and this second, and you know what I have some sentiments to this feature so let's put it third, come on guys, you're part of this industry I'm sure you know better and the reason it doesn't make it into C# 7 is because they don't have enough data!
Is nullability really such a big problem? I seem to hit almost no NREs in practice. Maybe younger programmers do not have such a rigorous mindset of contractual correctness?!
If you hit NREs all the time you need to reflect on what specific mistakes you keep repeating so that this happens so often to you.
any proposals logged for overloading all operators? including assignment like in c++
@pmunin You mean like the implicit
operator?
@GSPP it's not about whether you hit NRE it's about the measures that you need to take in order to prevent it and what happens if you don't do it!
It's not fairy tales it's actually an issue and on large codebases many times you don't want to prevent it, you just want to have it baked in and never think about it.
I _think_ that it's too late for having non-nullable reference types by default in the language so if I'm not mistaken static analysis is the way they will approach it where the compiler will provide warnings.
In my opinion it's not enough! because you will still have to handle it and prevent it yourself and have the same boilerplate (aka null checks) all over your code but I guess it's something.
@HaloFour
Yes implicit and here is example for assignment operator overloading which is not allowed now :
public static MyClass operator =(ref MyClass left, MyClass right)
{
....//Can create new instance, or change values of existing left instance
}
Just because non-nullable reference types won't make it into C# 7, that doesn't necessarily mean the team is delaying the feature so much as _not_ delaying C# 7 until that feature is ready. I'm excited about non-nullable references, and pattern matching, and tuples ... But if tuples are ready before those others, I'd just as soon have those sooner instead of having to wait until the team is ready to give us everything.
Non-nullable types will be a good thing when they come to C#, but we lived without them for 15 years; the world isn't going to collapse if we have to wait 2 more years. In the meantime, I find that the "billion dollar mistake" is not that much of a problem. You just need to be rigorous, and rely on careful code review and static analysis tools. I'm working on a pretty large app at work, and NREs almost _never_ happen.
@thomaslevesque yeah it's exactly what I'm thinking but the only downside is that we need to constantly add null checks everywhere before we use it, in the next version they plan to add static analysis and provide warnings afaik which is good but still, another issue remains and it's the fact that we need to bloat our code with null checks.
I'd really want them to solve the core problem and have something like in C++ where a const function must only make calls to const functions and so instead of functions apply this principle to author classes that are _safe_.
@march:
Do NOT scope nullability out of the C#7 time-frame. Push the release date back if you need to...
They've pushed back the release of any nullability features because they are still prototyping and trying to get it right. There's no use in pushing back the rest of the C# 7 featureset because one has been held back. Release what's ready to release, and wait for what isn't.
The nullability feature(set) would be of immense value to my own projects and my company, but you can't rush quality...
I think I need to go play with Swift and the like more. I'm rather confused on the true utility of non-nullable references. How would one construct a myrid of common data structures if nothing can be be null? For example, somebody explain to me a B-tree without nulls - 'cause my mind is not wrapping itself around that one.
Honestly, I'd much rather have more C-like stack declarations, borrowing semantics, and better support for pass struct by address than anything related to null semantics. I have sympathy for any language team as they attempt to address the needs/demands of an ever more fragmented consumer base.
@whoisj
The types themselves are still normal reference types. What changes is how you work with the variables of those types. If #5032 is implemented roughly as described, a normal reference type variable cannot be explicitly assigned null
or the result of any expression that _might_ be null
. If you need a nullable reference variable you instead append the ?
suffix, just as you do with nullable value types. Nullable reference variables are not of a different type, a string?
is still a string
, but the compiler will attempt to ensure that use of that variable is safe depending on the flow of logic prior to that access:
string s1 = null; // warning
string? s2 = null; //compiles fine
int length = s2.Length; // warning
var length2 = s2?.Length; // compiles fine, length2 is an int?
if (s2 != null) {
length = s2.Length; // compiles fine, s2 can't possibly be null here
}
length = s2!.Length; // compiles fine, but can NRE at runtime
There are a ton of edge scenarios, particularly around arrays and generics. The proposal gets into them a little bit.
@HaloFour my _beef_ with this proposal is warnings, I don't want it to be warnings, I really hope that the default will be an error and not a warning.
@whoisj null makes sense in many data structures. null ceases to make sense in the vast majority of data driven systems. The capabilities i want a software language to express are very different than the capabilities i want a system to express.
If I expect a User to have a UserId and an Invoice to have an OrderOpenDate it makes no sense to ever allow my system to continue when those would be null (or default in this case). In many situations default is even more dangerous than null. Atleast an uninitialized string or collection property will NRE upon access. An uninitialized date or id property will silently corrupt your system state up until it generates a key constraint violation (if ever).
@dotnetchris We have constructors to make sure objects are always initialised to a valid state; and encapsulation mechanisms such as method and property to keep the object in a valid state. I know that this is not always easy especially with things like serialisation and EntityFramework. The principle here is that it is up to the author of the class to establish and maintain invariance, which is IMHO not what the non-nullable reference type proposal is about.
If I expect a User to have a UserId and an Invoice to have an OrderOpenDate it makes no sense to ever allow my system to continue when those would be null (or default in this case). In many situations default is even more dangerous than null. Atleast an uninitialized string or collection property will NRE upon access. An uninitialized date or id property will silently corrupt your system state up until it generates a key constraint violation (if ever).
This reminds me of an issue we ran into with a partner who was coding their application in Go and could not support NULL values in their structures. Per the specification we both were working off of (third party authored the spec) we should return to them a set of strings. Any of those strings could be null (as in the data did not exist), and empty string was a completely valid value.
They found themselves in a fairly broken state for a while until they designed a resolution which, in my humble opinion, was over engineer and could have been solved with a simple nullable field.
So, as long as null
remains a viable and legal value when necessary, I'm all for non-nullable types; so long as they're used where they make sense.
@whoisj
So, as long as null remains a viable and legal value when necessary, I'm all for non-nullable types; so long as they're used where they make sense.
As far as I can tell that's the plan.
(I am however, opposed to multiple inheritance)
Is the following feasible? If yes, can someone please create proposal item?
Generic methods should be smarter:
using System.Collections.Generic;
public static class GenericMethodsShouldBeSmarter
{
public static void MyGenericMethod<TEnumerableOfTItem, TItem>(TEnumerableOfTItem enumerable)
where TEnumerableOfTItem : IEnumerable<TItem>
{
//Do something
}
static void TestExpectToWork()
{
var myEnumerable = new List<int>();
MyGenericMethod(myEnumerable);
/*
Compilation error:
Error CS0411 The type arguments for method 'GenericMethodsShouldBeSmarter.MyGenericMethod<TEnumerableOfTItem, TItem>(TEnumerableOfTItem)' cannot be inferred from the usage. Try specifying the type arguments explicitly.
*/
}
}
Url to gist: https://gist.github.com/15a3c31d550add7997d3ba55c293556f
C# Compile online: http://csharppad.com/gist/15a3c31d550add7997d3ba55c293556f
If TEnumerableOfTItem implements several IEnumerable<T1>,IEnumerable<T2>
... In this case compilation error is inevitable. But in case TEnumerableOfTItem implements just one IEnumerable<T>
, then I believe C# compiler has all the knowledge to resolve the generic arguments unambiguously.
@pmunin I _think_ that this would be considered as aggressive type inference something that as far as I read they have no interest in doing this but I could be wrong but anyway, you can look here #11359,
@eyalsk what you say would make sense in case there is a conflict. For example if TEnumerableOfTItem implements several IEnumerable<T1>,IEnumerable<T2>...
In this case compilation error is inevitable. But in case TEnumerableOfTItem implements just one IEnumerable<T>
, then I think C# compiler has all the knowledge to resolve the generic arguments unambiguously. I'm updating my previous comment with this
@pmunin yeah but sometimes it's not about whether it's technically feasible but whether they want to do it, it's a design choice, they can decide not to do it regardless to the possibility.
Besides that, you still need to think about ambiguity but this is covered in the posts I linked.
@pmunin I was surprised that this code does not work. Is https://github.com/dotnet/roslyn/issues/5023 not your exact request?
@GSPP Yeah it's probably what he wants, I already linked it to him. :)
@pmunin
Is the following feasible? If yes, can someone please create proposal item?
You can create your own proposals. Just click that New Issue button on the Issues list page. Generally set the title to "[Proposal] _Description Here_" and then in the body describe what change you'd like to see. Best to include use cases, code examples and an explanation of what's different.
Proposed ideas in this issue (or other) will most certainly get lost, and it's not terribly likely that someone else is going to bother to champion anyone else's issue to the point of actually writing up a proposal.
Will there be any alternative memory management policy in C# 7.0 to work together with GC? For example, reference count.
Or will there be any enhancement of GC itself? For example, https://github.com/dotnet/coreclr/issues/555 and https://github.com/dotnet/coreclr/issues/1784
What about https://github.com/dotnet/roslyn/issues/2212 ?
@ygc369 The C# 7 plans require no CLR changes, and therefore are not bound to any particular version of the CLR. Perhaps you meant to ask those questions in the dotnet/coreclr
repository?
@oscarvarto The C# 7 plans do not include any changes that require CLR support. That includes (or rather, that _excludes_) #2212.
Any thoughts on #11889 ?
Today I had a discussion with a new colleague coming from C++. He was trying to include mathematical functions for arrays. I told him I had created a utility class for this and he can extend it. This class is now about 4000 lines long for doing only basic math on arrays (in detail everything that System.Math has and all binary operations). Currently I have only implemented in float.
He looked at me with big eyes and asked: "How can such a language have ever established in the community?". And I really must agree. These ongoing discussion here are almost always around syntactic sugar - things that still exist - but making life in C# easier. BUT: There are things that cannot be done in C# - or can be done with tremendous efforts regarding coding and testing. I always hear: Create an interop library, but this is not what I want.
So when do we see the multiple times request features for math operations on generics or better the constraint for this.
@deepumi It's being discussed there...
@msedi
He looked at me with big eyes and asked: "How can such a language have ever established in the community?"
I can say many things about C++ and ask you the same question, not to mention that before C++11 many things were a _chore_, also, when you speak about C++ and compare it to C# you need to think about the audience.
These ongoing discussion here are almost always around syntactic sugar
Not true but if you think so you can always create an issue about it and share your thoughts or/and write proposals about things that you want to see in the language.
There are things that cannot be done in C# - or can be done with tremendous efforts regarding coding and testing.
There are things that cannot be done in C++ too without of course writing your own or using 3rd-party libraries, same thing applies to C#.
Can you please provide some examples?
So when do we see the multiple times request features for math operations on generics or better the constraint for this.
Can you be more specific? what exactly do you expect/want?
@msedi
You probably want proposals: #2147, #3255 and #3391. If those don't fit the bill I'd suggest creating a new proposal and spelling out, in detail, what you'd like to see the language to support. Include use cases and example syntax.
There are things that cannot be done in C# - or can be done with tremendous efforts regarding coding and testing.
If I were used to C# and trying to write something in C++ and I tried to apply a solution I was used to that would involve reflection I would probably say the same about C++. Switching languages frequently involves switching mindsets. Trying to apply one to another without understanding the differences can easily lead to problems. I might be able to drive in a nail by whacking at it with a screwdriver but it's clearly not how the tool is meant to be used.
There's also a lot of things C++ leans on libraries to accomplish. C++ without STL or boost?
This class is now about 4000 lines long for doing only basic math on arrays (in detail everything that System.Math has and all binary operations). Currently I have only implemented in float.
I'd wager that someone else already went to all of this trouble and has libraries to accomplish common mathematical operations across arrays like this.
@eyalsk
I can say many things about C++ and ask you the same question, not to mention that before C++11 many things were a chore, also, when you speak about C++ and compare it to C# you need to think about the audience.
Of course you are right. I wouldn't go back to C++. But there are things that all of use really need when it comes to the point of number crunching.
Not true but if you think so you can always create an issue about it and share your thoughts or/and write proposals about things that you want to see in the language.
Also true and maybe a little over exaggerated by me. Nevertheless there are things that are not really needed, like collection initializers, binary literals, digit separators, etc. Of course I would have needed them sometimes, but in the end everything can be done with the current language.
There are things that cannot be done in C++ too without of course writing your own or using 3rd-party libraries, same thing applies to C#.
Also true, but pointers to templates can be done without any efforts. In C#, NO.
There are things that cannot be done in C++ too without of course writing your own or using 3rd-party libraries, same thing applies to C#.
Yes, there are libraries, like the intel math kernel library. This library is now about 200MB large, for an application that is totally written in C#. And still there are not all features I need.
Here's an example of a very small Add-Routine:
/// <summary>
/// C = A + B
/// </summary>
/// <param name="A"></param>
/// <param name="B"></param>
/// <param name="C"></param>
[MethodImpl( MethodImplOptions.AggressiveInlining )]
public static float[] Add( float[] A, float[] B, float[] C )
{
return ArrayMathInternal.Add( ArrayHelperInternal.CheckArrayLength( A, B, C ), A, B, C );
}
/// <summary>
/// C = A + B
/// </summary>
/// <param name="A"></param>
/// <param name="B"></param>
/// <param name="C"></param>
[MethodImpl( MethodImplOptions.AggressiveInlining )]
public static float[] Add( float[] A, float B, float[] C )
{
return ArrayMathInternal.Add( ArrayHelperInternal.CheckArrayLength( A, C ), A, B, C );
}
/// <summary>
/// C = A + B
/// </summary>
/// <param name="A"></param>
/// <param name="B"></param>
/// <param name="C"></param>
[MethodImpl( MethodImplOptions.AggressiveInlining )]
public static float[] Add( float A, float[] B, float[] C )
{
return ArrayMathInternal.Add( ArrayHelperInternal.CheckArrayLength( B, C ), A, B, C );
}
/// <summary>
/// C = A + B
/// </summary>
/// <param name="n">Length of the array.</param>
/// <param name="A"></param>
/// <param name="B"></param>
/// <param name="C"></param>
[MethodImpl( MethodImplOptions.AggressiveInlining )]
public static float[] Add( int n, float[] A, float[] B, float[] C )
{
fixed( float* Aptr = A, Bptr = B, Cptr = C )
{
ArrayMathNative.Add( n, Aptr, Bptr, Cptr );
}
return C;
}
/// <summary>
/// C = A + B
/// </summary>
/// <param name="n">Length of the array.</param>
/// <param name="A"></param>
/// <param name="B"></param>
/// <param name="C"></param>
[MethodImpl( MethodImplOptions.AggressiveInlining )]
public static float[] Add( int n, float[] A, float B, float[] C )
{
fixed( float* Aptr = A, Cptr = C )
{
ArrayMathNative.Add( n, Aptr, B, Cptr );
}
return C;
}
/// <summary>
/// C = A + B
/// </summary>
/// <param name="n">Length of the array.</param>
/// <param name="A"></param>
/// <param name="B"></param>
/// <param name="C"></param>
[MethodImpl( MethodImplOptions.AggressiveInlining )]
public static float[] Add( int n, float A, float[] B, float[] C )
{
fixed( float* Bptr = B, Cptr = C )
{
ArrayMathNative.Add( n, A, Bptr, Cptr );
}
return C;
}
/// <summary>
/// C = A + B
/// </summary>
/// <param name="n">Length of the array.</param>
/// <param name="a"></param>
/// <param name="b"></param>
/// <param name="c"></param>
[MethodImpl( MethodImplOptions.AggressiveInlining )]
public static void Add( int n, float* a, float* b, float* c )
{
if( a == null )
throw new ArgumentNullException( "a" );
if( b == null )
throw new ArgumentNullException( "b" );
if( c == null )
throw new ArgumentNullException( "c" );
for( int i = 0; i < n; i++, a++, b++, c++ )
*c = (float) ( ( (double) *a ) + ( (double) *b ) );
}
/// <summary>
/// C = A + B
/// </summary>
/// <param name="n">Length of the array.</param>
/// <param name="a"></param>
/// <param name="b"></param>
/// <param name="c"></param>
[MethodImpl( MethodImplOptions.AggressiveInlining )]
public static void Add( int n, float* a, float B, float* c )
{
if( a == null )
throw new ArgumentNullException( "a" );
if( c == null )
throw new ArgumentNullException( "c" );
for( int i = 0; i < n; i++, a++, c++ )
*c = (float) ( ( (double) *a ) + ( (double) B ) );
}
/// <summary>
/// C = A + B
/// </summary>
/// <param name="n">Length of the array.</param>
/// <param name="A"></param>
/// <param name="b"></param>
/// <param name="c"></param>
[MethodImpl( MethodImplOptions.AggressiveInlining )]
public static void Add( int n, float A, float* b, float* c )
{
if( b == null )
throw new ArgumentNullException( "b" );
if( c == null )
throw new ArgumentNullException( "c" );
for( int i = 0; i < n; i++, b++, c++ )
*c = (float) ( ( (double) A ) + ( (double) *b ) );
}
The reason I have to deal with pointers is, that a regular for loop is way to slow. I did many tests with Parallel.For, Release/Debug Mode. Only the new SIMD instructions outperform the pointer performance. The current implementation are only for float, but I need them for many types.
There must be some more number crunching support in C# as it has also been requested from the group here that talks about .NET, GC, C# performance an general.
@HaloFour
You probably want proposals: #2147, #3255 and #3391. If those don't fit the bill I'd suggest creating a new proposal and spelling out, in detail, what you'd like to see the language to support. Include use cases and example syntax
All suggestions are coming to a point where you need a special interface IArithmetic that calls a generic Add
The data is completely stored in memory so there is no bottleneck from reading the data first. You can create an example using pointers and arrays and you will see the difference.
If I were used to C# and trying to write something in C++ and I tried to apply a solution I was used to that would involve reflection I would probably say the same about C++. Switching languages frequently involves switching mindsets. Trying to apply one to another without understanding the differences can easily lead to problems. I might be able to drive in a nail by whacking at it with a screwdriver but it's clearly not how the tool is meant to be used.
I'm coming from C++ and I know that there a difference between generics and templates. But in the end I don't care if there's a difference. The compiler developers need to solve this for me. And - since IL is able to use add on generic data it's only a problem of the language that it currently does not allow to do it.
There's also a lot of things C++ leans on libraries to accomplish. C++ without STL or boost?
For some things yes, for a lot of things no.
I'd wager that someone else already went to all of this trouble and has libraries to accomplish common mathematical operations across arrays like this.
That's the problem: NO. There are a few like Math.NET, but it's to slow.
@msedi Okay, fair enough, I completely understand what you're saying and I know C# has quite a bit to go in terms of helping developers write faster code.
However, .NET supports SIMD through vectors you can also look at corefx for the source, so maybe that's what you want/need.
It's unfortunate that you can't perform the same kind of optimization to your own types as in the vector case the CLR actually know about it but I also feel that this would _complex_ the language so it needs to have the _right_ abstraction that really fit C#.
Another way to approach this is write it all in C++ and either use P/Invoke
/C++/CLI
or making it as a service and then use something like named pipe(or any other kind of IPC) to get the data after it was processed but it's hard to tell what you're doing exactly to provide any kind of meaningful advice.
@msedi
And - since IL is able to use add on generic data it's only a problem of the language that it currently does not allow to do it.
No, IL can only safely add
numeric types. Anything else produces unverifiable assemblies. This is why there are requests for generic constraints on numeric types, which the CLR does not currently support. This is why C# doesn't allow it.
No, IL can only safely add numeric types
That's what I mean. IL can run on numeric types, but C# does not allow it, because of a missing numeric constraint. So why not direct the discussions to having finally the constraint? In the end of course it would be nice if the whole thing would work on every datatype that implements an operator. But it also seems to me that how operators are used in C# is not very well elaborated. It seems that this is subset of operator functions that work well with every .NET language.
Had a discussion with a colleague 5 minutes ago. He wanted to have a difference for + and +=. I had also requested this and the solution was to use functions for that. So if the workaround is always to use functions, why then have operators at all?
I also had many troubles with operators when I implemented them. Assume I have a few volume data 512x512x2000 stored in floats and do following operation:
C = (A + B) * 0.3 + (A +D) * 0.7
In the end the problem was that many volumes were generated in between as "temporary" volumes. But my memory ran full because the GC was not able to clean this up quickly. In that I came to the point to get completely rid of operators. Another reason was that interface do not support operators and I need interfaces.
Finally I cam to the result to get rid of operators at all and reduce everything to methods. The only problem is that on a certain point, like adding arrays I need to use them.
I would love to meet with the C#/.NET team to show our current efforts to see what C# is able to do in the high performance and number crunching environment.
@msedi
That's what I mean. IL can run on numeric types, but C# does not allow it, because of a missing numeric constraint.
Generic type constraints are part of the CLR. The C# compiler cannot add a new type of constraint without the CLR supporting it. The CLR does not have a numeric generic type constraint.
I would love to meet with the C#/.NET team to show our current efforts to see what C# is able to do in the high performance and number crunching environment.
There are many proposals on this repo to push for improvements in this arena. Many of them simply require CLR support, which raises the level of effort required a decent amount. The C# team is here, though, and likely has already read both of our posts. But if I were the C# team I would probably want to concentrate on proposals with reduced effort (particularly language-only) and with greater impact across the entire C# ecosystem.
@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 so you really need to think about whether the same C++ idioms would make sense in C#, maybe they can add some C++ features in the context of unsafe
for people that really want to tweak a bit more.
@HaloFour I read @gafter post about CLR changes #420 but it's quite old, I wonder when these changes will be implemented, if ever. :)
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 [email protected] 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.
@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.
@eyalsk:
maybe they can add some C++ features in the context of unsafe
That would be completely OK for me.
@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. :)
@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
.
@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.
@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.
@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.
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 [email protected] 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.
@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.
@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
.
@manishki007 This is not the place to make feature requests or proposals. Please open a new issue.
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
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.
@thomaslevesque I just updated my question with example where combination of those features would be nice and make perfect sense
@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.
@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 So invisibly for developer eventually [Validate(v=> ...)] can be converted behind the scene to something like this: There are bunch of invisible class generation happens for anonymous delegates, yield return, await,... Cannot it be used here similar way?[Validate(typeof(<AttrConstructParameters1>))]
...//property declaration
class AttrConstructorParameters1 //invisible (nested?) class
{
public Func<object, bool> Parameter1 = new Func<object,bool>( v=> ... );
}
@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")]
.
@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!:
@optikos
Nullability is only somewhat helpful. Async support is many magnitudes more important, the same level as generics if not higher.
@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.
@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.
@Marusyk Checked exceptions are not on our plans for C# 7.
@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.
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 https://github.com/dotnet/coreclr/issues/6439
@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.
@gafter
Library requests belong over at the https://github.com/dotnet/coreclr repository
I think you mean https://github.com/dotnet/corefx.
@jamesqo
I think you mean https://github.com/dotnet/corefx.
I'm fairly certain @gafter is correct. https://github.com/dotnet/coreclr/blob/master/src/mscorlib/src/System/Buffer.cs
@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.)
See https://blogs.msdn.microsoft.com/dotnet/2016/08/24/whats-new-in-csharp-7-0/ for a _very_ up-to-date status.
Do the tuples work with params?
void m(params (string s, int i)[] args) { }
call with
m(("a", 1), ("b", 2), ("c", 3));
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
@soroshsabz See #115. But it didn't make the cut of features slated for C# 7.
@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.
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
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
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
@alireza-naghizadeh
C# 6: (myObject.MyStringList ?? (myObject.MyStringList = new List<string>())).Add("something");
And what is wrong with two lines?
@alireza-naghizadeh
myObject.MyStringList??.Add("something");
look like myObject.MyStringList?.Add("something");
@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
@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>();
@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.
@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
@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.
@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
@alireza-naghizadeh please create a separate issue for this suggestion
@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.
@alireza-naghizadeh myObject.MyStringList = myObject.MyStringList
is bad idea when not null.
@Cologler agreed but ??=
would still see a ton of use from me for other scenarios, like return x ?? (x = CalculateX());
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 };
@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.
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.
https://github.com/dotnet/roslyn/issues/5032#issuecomment-251372228
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;
Yes please. I don't even care that it would have to infer types outside-in; this one pattern is such a common pain.
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:
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.
@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"
@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.
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.
@pmunin
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.@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.
@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.
}
@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.
@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.
@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.
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.
@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.
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.
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.
@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.
@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
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 passthis
to another class as in your example,Node
will receive a reference to aMyGraph
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. =)
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.
just created proposal #15610
@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.
@HaloFour answered your copy.
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
2) 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
3) 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
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.
@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:
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.
@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:
c#
SomeDelegate oneTimeHandler = null;
obj.SomeEvent += oneTimeHandler = (s, e) =>
{
obj.SomeEvent -= oneTimeHandler;
// ...
};
@jnm2 you can also use a local function in that scenario ;)
Oh I guess! I can hardly wait!
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.
@nikChao I am unsure why you write such mappers in the first place. What advantage would your mapping feature have over AutoMapper?
@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.
@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
@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.
@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.
@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.
@gdefraiteur seems like you are reinventing the squared wheel. use the nameof
operator and dictionary initializers.
and what about being able to use out or ref optional parameters?
@gdefraiteur There is nothing in C# 7 about optional out
or ref
parameters.
@gafter
Thats why i make the proposal no?
@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.
@gdefraiteur we are no longer soliciting ideas for new features for C# 7.
@gafter Started on a C# 8 list yet?
@yaakov-h Not really, though if we did have a corresponding list for C# 8, that would not be the place to make proposals.
@gafter Is https://github.com/dotnet/roslyn/blob/master/docs/Language%20Feature%20Status.md updated to reflect the current plan/roadmap/status?
We don't yet have plans for future releases.
@gafter
Have roadmap for C#8.0 now?
@ygc369 I'd not expect that until C# 7 is shipped. They're pretty busy. =)
And C# 7.1. And C# 7.2.....
We've discussed so many ways to improve performance, but C#7 only implement few of them. This is very disappointing. C# is a "beautiful" language, the only lack is performance, especially about GC.
GC is a very outdated concept. .NET needs to move to Automatic Reference Counting (as did Objective-C / Swift). It has all the programming simplicity and safety benefits while also having immediate deallocation / performance benefits.
It's hard to say whether C# will EVER be able to move over to a different/faster memory model, whether GC is embedded far too deep to ever be replaced. Wouldn't bank on it.
@marchy Been there, done that. ARC means manual reference cycle breaking, and a lot of attention to object lifetime everywhere. Especially nasty is this with lambdas ("week self" for access to properties in lambdas, anyone wants?). This will silently make virtually all the existing code leaky and therefore invalid. I bet that the "improvement" you are proposing will not be accepted by both the language design team and community.
@vladd thanks a lot for that. Yes, there does mean people need awareness of memory. Deciding which component affects which other one is extremely important and does NOT go away in GC scenarios. We spun up specialized, senior teams on C# to chase memory leaks on .NET, particularly because they are that much more hidden and hard to discover when awareness by teams is not had at all (event subscriptions, callback patterns that hold strong references to object).
"weak self" is indeed annoying and not the most elegant solution (perhaps weak should be default for lambdas on Swift), but overall for the most part it DOES just works, while coming with none of the performance & memory demands that GC-based systems provide.
There's a reason Apple deprecated garbage collection on the mac after ARC came into the picture.
Developers aren't schoolchildren... it's a level of balance between simplicity that the .NET community can absolutely can handle. NOTE that I am not making a case for MANUAL reference counting (C++ and pre-ARC Obj-C days).
@marchy You were also the one saying that C# would die if non-nullability wasn't in C#7. Asking the C# language designers to make enormous breaking changes (in the runtime rather than the language, even!) is pointless. Please look around yourself, read others' opinions, and accept the fact that you're very isolated in your position.
@marchy For me, most of time I don't really care about _exact_ object lifetimes.
The same way as I don't care about alignment, about exact physical representation of lambdas, about overhead of storing the string length along with strings, about special magic which delegate makes to turn an instance method into something which looks like a free function, about exact shape of the state machine which compiler creates behind the scene for async methods and about a ton of different other technical details. I don't want the language to force me into considering them for each and every line of code, this would mean that my productivity as language user would drop to the native language level.
If controlling some of the details matters in some special case, I do the manual solution, the language allows me that. (Or in the rare event when it doesn't allow, I implement a part of the program in native code.)
(And by the way, ARC is not so innocent. Consider leaving a UI page which usually involves killing the last reference which holds a large object tree in memory—this will make the tree be destructed and run the destruction logic synchronously. This is certainly not better than GC slowly chewing on the tree in background.)
@marchy A generational tracing GC is performant enough for the vast majority of cases in which C# is being used today (or Java for that matter), as evidenced by the fact that these languages continue to be among the most widely used. So I really doubt the .NET team is going to make the huge investment to switch to a different form of memory management any time in the foreseeable future. Personally, I'd prefer that performance improvements are focused on the lower hanging fruit that will benefit a much wider range of .NET developers, such as making LINQ (at least LINQ-to-objects) more performant with aggressive in-lining, stack allocation, loop fusion, etc.
@timgoodman
@marchy
@vladd
@SolalPirelli
@gafter
@HaloFour
I think that GC should not be replaced, no one wants breaking changes. But ARC should be introduced into C# as an alternative memory management, it can work together with GC. For example, ARC collect most of garbage objects that are not in ref cycle, GC collect the left garbage objects in ref cycle. For default, CLR should use GC as before, no breaking change. But if someone wants to use ARC in some cases, he must use special syntax to tell the compiler or CLR.
For example:
var gc_obj = new object(); // gc_obj should be managed by GC
var arc_obj = arc_new object(); // arc_obj should be managed by ARC
In above example, I use syntax "arc_new" to alloc a new object managed by ARC. Of course, it only means that it can be collected by ARC, but it can also be collected by GC if it's in ref cycle.
I think this idea would perfectly resolve the conflict between GC and ARC.
@timgoodman
@gafter
@HaloFour
@MadsTorgersen
@erik-kallen
@khellang
@SolalPirelli
@dsaf
@vladd
I have many other ideas about GC optimization:
I hope more people are interested in above ideas.
@marchy Reference counting is as old as GC (both were from 1959). GC is not outdated for specific use like converting _too_ large free memory to extra throughput in a system (and mostly only when the latency is not cared about); it is just an _optimization_ being abused.
Your argument about _awareness_ still seems too weak. The fact is, there are always limited resources available to solve problems by concrete machines in reality, so people _should_ know how to manage the _onwership_ of resources in their solution of problems to make it logically consistent (e.g. _before coding_, keeping the design without any suspicous loop of dependencies to break at runtime, unless they are introduced by input of the solution). Otherwise, the solutions are _inadquately designed_ because part of problem-specific work derserved to be solved is missing. Note there is no known "heuristic" algorithm which can beat well-trained humans for specific purpose (to resolve such inconsistency) _in general_, since there is no one-thing-fit-all way to tell the implementation the precise intention of the problems being solved and to guarantee it optimzed. Further, memory is _just_ one kind of such limited resources.
I'd also note automatic resource management (RAII/RRID idiom) in C++ comes far earlier than ObjC. Notably, it is not only effective on memory; it can work on other resources like locks and database connections. And it needs no compiler magic.
@vladd The lifetime of particular objects may be trivial like alignments as implementation details, but the overall results are not similar, e.g. resources may be difficult to reclaim if you know nothing about lifetimes, which can be treated as plain leaks by users.
I think being ignorant of any object lifetime _by default_ can only work in speicific scenes, which mostly need only several DSLs rather than a general-purposed language. Otherwise, it is generally infeasible and methodologically ill-formed, unless you don't care end-users' need: because you can't estimate how many leaks the end-users can tolerate. And even all industrial users can allow this silently, system performance (also the cost on hardware) is already unnecessarily wasted _a lot_.
To tweak the process about how to release the resources is another story after you can guarantee the deterministic behavior _in time_.
An addition note on language design: modern Lisp dialects (esp. Scheme family) has better reasons to mandate _unlimited extent_ of objects because a) objects are not bound to probable side effects on release (which is also true for many other languages) and b) both proper tail call optimization and undelimited first-class continuation are needed as killer features.
I don't see any other theoretical reason to make unbounded indeterminsitic mechanism like GC required _by default_ in a general-purposed language.
@FrankHB
写了这么多啊,大概看了下,你是支持引用计数的,对吧?
@ygc369 what kind of stuff are you building if you are _that_ passionate about GC optimization? Anyway I am waiting for a production-ready C# 7 release before being interested in any further features.
Developers aren't schoolchildren...
The amount of script kiddies I (and a few others) deal with on helping to use Discord.Net says otherwise. Some even come in with zero understanding of programming in general, thinking that using a relatively complex lib to make a bot is a good Programming 101 exercise.
@ygc369 怎么突然有了一股钦定的感觉呢……
实际上我没直接提的是大部分场合引用计数都用不上。
The list of features for C# 7 can be found here in the csharplang repo.
We're using that repository for language proposals and discussion now.
I would like to add the alternative keywords:
1) not for ! so:
if (not isDone) { ... }
instead of:
if(!isDone) { ... }
2) and for && so
if(isDone and isPassed) { ... }
instead of:
if(isDone && isPassed) { ... }
or for ||
nor for !(a || b) operation so
if(isDone nor isPassed) { ... }
instead of:
if(!(isDone || isPassed)) { ... }
5) nand for !(a && b) operation so
while(isDone nand isPassed) { ... }
instead of:
while(!(isDone && isPassed)) { ... }
6) extend const keyword for immutable variables:
const testRunner = new TestRunner();
instead of:
var testRunner = new TestRunner();
7) make ; optional, may be used it when separating 2 statements in one line.
8) true/false for truthy and falsy:
if(false customerList) { throw new Exception("Customer list cannot be null of empty.") }
@lemadane commenting on a closed issue is not likely to get anything done. I suggest you look to see if there are any issues suggesting any of these things, and comment there, or open a new issue otherwise.
@lemadane I do think there are existing issues covering most of your suggestions.
Most helpful comment
I guess the features that would reduce developer errors most are:
var! dog = new Dog();
let age = 26;
immutable int age = 26;
public immutable sealed class Dog { ... }
[Requires(...)]
[Ensures(...)]
requires ...
,ensures ...