@davewill: We have safety rules in the language, so that things on the stack won't escape their scope. For instance, a ref-returning method has a notion of "safe to return": it will only return refs that either a) came from the caller as parameters, or b) live in the heap. Meanwhile, the caller knows that the ref returned to them is only safe to return if all refs passed in as arguments were safe to return.
For the heap (that is, objects and structs within them), refs to internal structs are already tracked by the GC, and these features don't change anything about that.
@kcdiaz: He so did! And he's not the first. AND he won't be the last! :)
@vb123: I was deliberately avoiding the `:` syntax, so that we could use that if we ever do the "implement an interface" bit I speculate about at the end.
@david_n_m_bond: That is exactly one of the subtleties we are debating. To what extent should an assembly "opt-in" to being interpreted with non-null intent? If we choose that it should opt in, then the compiler can stick an assembly-level attribute there to that effect.
@Kryptryx: We very deliberately avoid having a syntax for "non-nullable". In the future, good code will mostly have non-nullable in signatures, with a sprinkling (10-20%?) of nullable. At least that's our working assumption. With our current plan, such code will be beautiful. With explicit `!`, that same code will look like it's swearing at you. It's better (we think) to have a beautiful future, and deal with transitional challenges outside of the language syntax.
@Stilgar: We won't do something that feels like a breaking change. If that's the best we can do, we won't do it. I'm not hell bent on the nullability feature. I'm determined on chasing it all the way to the best we can possibly do. If that's not good enough, then we'll put the feature to rest knowing that it just doesn't have a place in C#.
@PurityControl: It's a great idea to allow functions with out parameters to be called as if they were tuple-returning, having the compiler do the magic like in F#. Another possible convenience is allowing a tuple to be passed to a function that can take the individual members of the tuple as arguments.
@N2Cheval: Sounds like a big feature. We'd probably need to see a somewhat more fleshed out proposal to understand what you are getting at. But I have to say that reifying more metadata at runtime is not the direction I see us going. On the contrary, with native compilation we are challenged by the ubiquitous access to even the metadata that is there today. But maybe I'm misunderstanding the proposal.
@Alex: I don't think it's borrowing from Swift as much as borrowing from the same places that Swift is borrowing from. :) However, I see Swift doing something we've also often done, which is to take concepts from less widely adopted languages and pulling them into the mainstream. Option types (or "optional types" as the Swift guys call them, which irks me because that used to mean something else) are a well known pattern from functional languages that Swift has - rather successfully I think - integrated into a more imperative setting, and found a way to blend with the legacy Objective-C libraries. That integration depends heavily on pattern matching to do the null checking (like in the functional languages it comes from). I don't think we have that option (no pun intended), because we already have established ways of checking for null in C#. Any feature we do here would have to recognize when folks are checking for null, rather than force them to do it in a new way. That would be a disaster!
@Stilgar: Those are our worries too, and one of the reasons we haven't done this in the past. I agree that '!' everywhere is ugly. I'd rather not have the feature than recommend that! Here's the way that I think about it:
I think nullable reference types is the most important part of the feature. Since this is new (and uncontroversial) syntax, it doesn't break anyone's existing code in and of itself - not even with a warning. They way we would make it work is, that if you dereference one of those - say a "string?" - we would give you a warning only if we can't see you checking for null. We will do a flow analysis similar to definite assignment, and if for instance you are inside an if-statement and have just checked that the thing is not null, then we're happy to let you dereference without warning.
This means that if you add '?' to any member, for instance, you will get warnings in the places where that member is dereferenced without first being checked for null. You can then go and insert null checks, and we will probably also have syntax to let you easily override if you know it is not null. (In fact we would probably use '!' for that - as in 'p!.Name', where 'p!' means p assumed to be non-null. (I suspect it will be known as the "dammit!' operator).
Non-null reference types are actually less important I think. They prevent fewer mistakes: they prevent assigning null into something. Ok. And they would prevent forgetting to initialize a member that's supposed to be non-null (but whose initial value is null) in a constructor. I don't think this warrants its own new syntax, especially due to the damage it would do to the beauty of code.
I think a number of people will want to say: well I marked all my nullable types, I think. Can you please check that I use the rest in a non-nullable manner? If I don't, I may have forgotten to mark some, or I may have found a bug.
I'm quite open to that check being opt-in - maybe it's even a Roslyn analyzer, not something the compiler does.
There's a lot more subtlety still. The design notes etc. on GitHub, however messy and as-you-go, are the best source of the full discussion we've had.
@aarondandy: this is a great observation. We've had a lot of design discussion around interaction between existing code (compiled without the new null feature) and new code, and we have some ideas for how to avoid situations like you describe. The main idea is that operations involving existing types (which are in a sense both nullable and non-nullable) do not generate warnings. Your program above would not yield a warning on the assignment you indicate.
This means that when it comes to interacting between todays null-unsafe code and tomorrow's somewhat-less-unsafe code we would sacrifice safety rather than yield spurious warnings.
@electricninja33: Yes, the pattern version of the "is" operator is another way to introduce a variable inside an expression. We need to figure out all the same things as we did for "declaration expressions", such as what is the scope for the variables etc. They are not exactly the same feature, though, and I can actually imagine us adding both.
@electricninja33: Some caution is warranted around unsafe and iterators/async. We may have erred too far on the side of caution, though, and blocking valid useful scenarios. Can you raise an issue with a bit more detail on github.com/dotnet/roslyn and maybe post the issue# back here to close the loop? Thanks a ton in advance!
@dcuccia: whoa, wanna save some good stuff for C# 8, right? ;)
@VivekRagunathan: glad you liked the duality bit. This has actually been a target of academic study for decades. Some good references may be found in this paper, written by some weirdo professor type I knew once.
@mjjj: We didn't initially realize the utility of this for invoking delegates or void returning methods, and our first prototype didn't allow it. We started out calling it the "null propagating" operator, so if there was nowhere to propagate to, what would be the use? :). Luckily we got our minds on the right track, thanks in large part to community discussion on CodePlex, and tweaked the feature in the direction of "null conditional".
@T_D: Yes, ArraySegment<T> is that. It is barely being used, and we wonder why. We want something that is a little more general and efficient, and can for instance serve as a window onto unmanaged memory. We may or may not add language syntax for the type, or for the slicing operation. We'll see when our thoughts are a little further along.
@JohnLudlow: Great example! Especially when you think about writing the async version, right? At that point out parameters go from a bad option to not an option at all.
@r2dnb: we are actually excited about adding better nullability checking to the compiler. If you check us out on GitHub, you can see some of our thoughts on that.
It's not an easy thing, though, to add to a language that's out in its v6 already. It takes a lot of work for us to get it right, and that work takes time. But we are trying, and hopefully by C# 7 or C# 8 we will have worked it out and put it in the language!
We implemented await in catch and finally for C# first. It was exceedingly complicated, and the truth is we ran out of time to do it with high confidence in VB, just as some features also had to be dropped from C# at the last minute for lack of runway to do it well. I expect us to want to do it in the next version of VB.
For the record, a lot of the VB 14 features actually reduce the gap between VB and C#. Please check out the feature list on GitHub. Many of the new VB features were already in C#.
Whether to stay with VB or move to C# is ultimately a business decision you'll have to make based on the sum of factors affecting your specific situation. I can say that the value added to VB in VS 2015 is simply astounding: Lots of new language features, completely revamped IDE with refactorings, Roslyn analyzers and fixes, greatly improved debugging, etc., etc. From the core language experience point of view, this is the biggest renewal of VB in a long time.
You are right, the slides are broken. I've started to ask around to see if we can get it fixed.
The "good" news is that there isn't a lot in the slides. Almost the whole session is demo. The only slides with anything interesting in them occur before we start demoing, in the first few minutes of the talk, so you can just watch a few minutes of the video to see them.
I'll post back here if/when I learn that the slides are fixed.