
C# 7 Proposal: Nullable reference types and nullability checking - Permit
https://github.com/dotnet/roslyn/issues/5032
======
alkonaut
While I think these C#7 proposals are all cool features (Non-null, tuples,
pattern matching), it feels almost like it's too late to make improvements of
this kind to C#. We have had F# for a very long time, do we really need non-
null and pattern matching and so on in C#? The features sure make sense for
C#, but do they make sense _now_?

As more and more features come into C#, all of the BCL would have to be
updated to use them if they are to deliver their full value. When generics
entered in .NET 2.0, the generic and non-generic collections API were both
included in the BCL, and they still are. I can't see how it would be as easy
to make the BCL take full advantage of proper tuples, non-nullables etc., in a
way that doesn't feel like a complete afterthought.

I'm all for adding features, and I'd be happy to get _breaking_ changes and
update thousands of lines of code to get them. But I fear that isn't going to
happen, instead things will come in as optional features, the BCL won't be
updated to return tuples where it should (I.e. whereever it _would_ have if
the feature had been around forever), and so on.

~~~
sedatk
F# syntax is too verbose for OOP. Actually functional parts are too, like
lambda syntax, LINQ etc. Unless it's improved C# is bound to remain
mainstream.

~~~
MichaelGG
Can you explain? In C#, for example, type inference barely works. You have to
do e.g.:

    
    
      Func<int, int> inc = x => x + 1;
    

In F#, this is just:

    
    
      let inc x = x + 1
    

Based off a simple test (coded same thing in both languages), C# requires
about 20x more type annotations. Fields, methods, type parameter constraints
-- C# simply doesn't implement type inference in most places.

You're right that F#'s lambda operator (fun) should be shorter. I'd prefer \\.
i.e. map (\x.x+1)

But verbosity isn't the reason C# devs don't switch to F#. Hell, it's still a
"thing" to decide if using "var" is ok.

~~~
Locke1689
That's not a "problem" in type inference, that's a design decision where
lambda syntax can represent either delegates or expression statements. This is
how LINQ-to-SQL can take a LINQ expression and turn it into a SQL statement.

However, that doesn't mean we don't wish you wouldn't have to specify the type
there -- that's why there's a separate proposal for local functions
([https://github.com/dotnet/roslyn/tree/features/local-
functio...](https://github.com/dotnet/roslyn/tree/features/local-functions)),
which would allow

    
    
        var inc(x) => x + 1;

~~~
MichaelGG
Yeah, I know the reasoning, I just find it faulty. It's confusing to not know
if your code is code or turned into an expression tree.

So with that, local functions will have different syntax than normal
functions? I don't envy y'all on the C# team; it's gotta be difficult to try
to advance it while maintaining backcompat.

I just wish MS would put more money and clear marketing into F# instead of
pretending like hacking up C# syntax is the only way to continue.

~~~
Locke1689
I would read this[1] article on F# if you want the realities of the situation

[1]
[http://ericsink.com/entries/fsharp_chasm.html](http://ericsink.com/entries/fsharp_chasm.html)

~~~
MichaelGG
That's an excellent post as Eric's a smart guy yet misses the real reasons.

Eric's wrong about Swift, and the reason is illuminating. Swift has the full,
unconditional support of Apple. Look at the splash pages for Swift[1][2].
There's no comparable page for Obj-C. The docs on Swift[3] make it clear that
you're totally set and don't need to worry. It's obvious to any developer that
choosing Swift is a good, safe, correct choice and you won't be left hanging.
Microsoft chose not to do this for F#.

Now compare to how MS markets C#[4] vs F#[5]. C#'s clearly sold as the general
dev language for "rapid application development", whereas F# is to "solve
complex problems ... such as calculation engines and data-rich analytical
services". This sums up MS's attitude, which percolates to customers. F# is
just for hyper-intelligent folks doing mathy stuff - not for us normal devs!
C# should instead be pitched focusing on it's "familiarity and userbase" just
like VB has "English-like syntax which promotes clarity"[6].

Inside VS and .NET overall, it's clear that F# is simply not getting the same
level of support. So while Eric might be pointing out that "normal people",
meaning the bulk of MS customers, are staying with C# this is just MS
fulfilling it's marketing goals. MS refuses to reassure customers that F# can
and should be considered for any application where C# is considered.

Until that attitude changes, I would not be surprised if customers continue to
do what MS says to do. I doubt it'll change. C# has no real competitor (Java's
lightyears behind). They've got a proven track record of ignoring F#. Add in
the politics and face issues going on (going off the history as well as
comments from third parties that have been involved on both sides) and well,
what can we really hope for?

1: [http://www.apple.com/swift/](http://www.apple.com/swift/) 2:
[https://developer.apple.com/swift/](https://developer.apple.com/swift/) 3:
[https://developer.apple.com/library/ios/documentation/Swift/...](https://developer.apple.com/library/ios/documentation/Swift/Conceptual/Swift_Programming_Language/)
4: [https://msdn.microsoft.com/en-
us/vstudio/hh341490.aspx](https://msdn.microsoft.com/en-
us/vstudio/hh341490.aspx) 5: [https://msdn.microsoft.com/en-
us/vstudio/hh388569.aspx](https://msdn.microsoft.com/en-
us/vstudio/hh388569.aspx) 6: [https://msdn.microsoft.com/en-
us/vstudio/hh388573.aspx](https://msdn.microsoft.com/en-
us/vstudio/hh388573.aspx)

------
DiabloD3
I completely agree with this proposal, especially since this seems to be opt-
in, otherwise a lot of "probably bug free" code would suddenly break.

If this makes it into 7, a lot of code should at least be attempted to be
converted to this to cut down on an entire class of bugs.

Seriously, Microsoft is making me happy that they're taking the whole
"languages should make the job of the programmer easier, not harder" thought
process seriously.

~~~
jimktrains2
I only used C# for a few months, a few years ago, but I immediately loved the
language. I wasn't thrilled about the documentation (Why aren't return types
listed in [1]?), VS (OK, vim key bindings made more bearable), or just dealing
with the MS ecosystem in general, but I loved the language.

It felt like everything Java was suppose to be, but is failing at.

[1] [https://msdn.microsoft.com/en-
us/library/system.string%28v=v...](https://msdn.microsoft.com/en-
us/library/system.string%28v=vs.110%29.aspx)

~~~
mattmanser
Because it's a statically typed language it's all in the IDE. Almost everyone
who uses C# doesn't need to check the documentation for that kind of
information, it comes up when you're typing, or it's an ctrl-space away if
your caret is on a method, or you can right-click go to definition.

You can pretty much right click on anything and go to definition, which will
show you all the method signatures and return types of everything.

My only beef with the documentation is that they show examples of the code in
use, but annoyingly never the output. So, for example, it's never clear even
from the examples in the documentation whether a directory path or a URL
includes a trailing slash or not. And because there's no REPL, you have to
either build/compile/run or use an external program (I used to use some LINQ
tester program that was basically a REPL, but it's contextually almost as
expensive as simply trying it in an existing program).

~~~
Locke1689
> And because there's no REPL

Working on it -- you can expect a public pre-release soon. The code is in
master right now:
[https://github.com/dotnet/roslyn/tree/master/src/Interactive...](https://github.com/dotnet/roslyn/tree/master/src/InteractiveWindow).
I'll have to check with the dev to see how installing it is supposed to work,
but he demo'd it on Friday and it looked very slick.

~~~
mattmanser
That will be a wonderful addition!

------
inglor
There is no way they can introduce a breaking change _this big_ into the
language. This change effectively breaks almost every big piece of C# code.

~~~
mikko_m
As described in the proposal, it's supposed to be an opt-in feature.

~~~
inglor
It would be impossible to _actually_ have a feature like this as opt in since
it would effectively create two different versions of C#. What the proposal
does is emit warnings (and not errors) which is another shame.

I'd much rather have it opt in at the class declaration level like:

`strong class Foo`

Where strong means references to it act like value type references with
regards to nullability.

Alternatively, they can just fork C# and remove all the weird parts they've
accumulated over the years and stay with a sub-language that's more powerful
and they can add useful features on top of.

~~~
jeswin
> would be impossible to _actually_ have a feature like this as opt in since
> it would effectively create two different versions of C#

You still haven't said what's wrong with the proposal. There are multiple
versions of C# already. Emitting warnings seems to be a good compromise, given
there is already an option to treat warnings as errors.

>`strong class Foo`

This is a slippery slope. Next time they add another feature for correctness,
they'll have to add 'stronger class'. This is akin to "use stricter" proposed
by Sound Script (JS).

~~~
jaked89
In big codebases, warnings are useless. No one reads them.

They usually contain thousands of items from different plugins, designers,
etc. Sorting through them all is impractical.

Errors are not just about protecting a developer from himself, but more
importantly, protecting developers in a team from one another.

If the compiler can't produce an error, the whole feature is pointless.

~~~
DrJokepu
I worked on some fairly large C# projects where the teams had zero-warning
policies. It's not that difficult to achieve with a bit of discipline.
Warnings in third-party dependencies only show up if you build them from
source, but these days it's a lot easier to get your third-party dependencies
from NuGet instead.

That being said, I don't think warnings would be a good way to go on this
case, because the sheer number of warnings generated by these new rules in
existing, large (and mostly bug-free) projects would make it very difficult to
reestablish a zero-warnings state. Developers on the team will just get
undisciplined due the the broken windows effect.

~~~
AndrewDucker
Yup. We have a zero-warning policy, and there's a setting in every project you
can enable to treat warnings as errors, which we use.

------
MichaelGG
This does not belong in C#; this belongs in the CLR. If they don't do this as
an upgrade to the CLR, then they are effectively admitting that "common
language" is dead and a joke, even more so than now. (Where libraries, even
MS-shipped, make API decisions based on C# compiler implementation details.)

On the plus side, they're finally talking about something that should have
been addressed back in 1999.

The downside is that C# seems to be getting a lot more complicated due to
having to graft this stuff on in an ugly way. I agree the language needs tons
of work. I just wish they had better fundamentals so it was neater. F# already
has most of what C# can aspire to be, but it feels far less complicated.

~~~
dogma1138
I'm not sure what you mean exactly but there are already differences between
various .net languages there are things you can do with C# that you can't
really do with VB.NET easily even simple things like bit-wise operators or the
fact that you have literal control of overloads in VB which you lack in C# and
the list goes on and on.

Since the languages them selves work quite differently the interpreter and the
CLR can't really treat them the same way heck if you make something simple
lika a hello world in VB and C# the MSIL won't be identical.

And with the current nullable support then currently supported Nulleable Type
Values for VB.NET and Nullable Types for C# don't really work exactly the same
way because they still need to conform to the specification of their language
first and then to the CLR.

~~~
MichaelGG
The idea is that major type features should be exposed via common metadata and
represented in the IL. This allows other languages to unambiguously use such
types. Non-nullable references are definitely a big enough feature.
Conceptually, it's bigger than Nullable<T> which is just a wrapper you can
toss around any struct and could be done purely as a library (though I
understand there's some delicacy as far as unboxing null and converting that
to a Nullable<T>).

I'm not sure which interpreter you're referring to, but languages don't need
to emit similar IL for executable code (why would it matter?). What counts is
that the type defs end up exported in the same manner. If making a class in VB
emitted substantially different IL than C#, that'd be an issue.

------
Maarten88
I have not even started using C#6, which introduces the Null-Conditional
operator. I expect this to already cleanup a lot of that verbose null-checking
code, and avoid null reference exceptions simply because checking for null
gets so much easier.

To me, as a C# dev, this proposed change seems rather quick (let C#6 get some
use first) and it also seems not consistent with nullable value types: with a
reference type you'll get a compiler warning where the same error on a value
type will give an error.

~~~
CmonDev
Two year release cycles are quick for you?

~~~
Maarten88
No, but Visual Studio 2015 came out July 20, only 7 weeks ago. I've been using
it 3 weeks now. I find it difficult to judge a proposed feature when there was
so little time to get used to the current situation. Maybe it's a great idea,
I don't know. It looks like the next step beyond the Null-Conditional
operator. I'll be migrating a lot of code to use that in the coming weeks.
After that I'll have a much better idea how much I like this idea.

~~~
ygra
It's a proposal. It doesn't even have to be implemented in the language for
the next version. The C# 6 proposals were done a long time ago as well, and
some didn't make it into the language after all.

What would you have the language designers do? Wait two years before even
thinking about what to work on next?

------
dep_b
I always advocated for this kind of change in C# and now I'm using Swift I'm
definitely sure that non-nullability should be available in any kind of OO-
language. There aren't that many use cases that require nullability of a
reference and there are many cases where the forced nullability bites you.

Unfortunately adding it to C# now will mean that either the language breaks or
the feature will be an add-on that isn't as powerful as it should be (like in
Swift, where it's really the base for everything).

Personally I would say that a reference type can be declared explicitly non-
nullable with an exclamation mark (!) and if they're properties they either
should have a default value or they should be set while the class is
constructed.

------
harigov
I thought the idea behind .NET CLR was to make it easier to use whatever
language makes sense for the problem without worrying about whether it can be
integrated into the overall system. By making C# into a language for
everything, MS isn't using strengths of .NET to its advantage. I would much
rather learn 10 easy languages that work together than a single, complicated
monster of a language that I can never wrap my head around (read C++).

~~~
ygra
I'd argue that C# is still much simpler and easier to understand than C++. But
in any case, one major problem with .NET and multiple languages in a single
project is that a compilation unit is an assembly. So you can write one
assembly in one language and another in a different language, but that's about
the extent of being able to mix languages in a project. Which just may be not
fine-grained enough.

~~~
titanix2
Actually assembly is the minimal unit of deployment, not compilation. The
minimal unit of compilation is the netmodule[1]. You can compile from
different languages as netmodules, then link the resulting netmodules together
in an assembly.

By the way, this is not a scenario supported by Visual Studio, so it requires
using command line tools. So for any practical purpose, you're right that
multi-language solution require the use of multiples assembly projects, which
is tedious.

[1]
[http://blogs.msdn.com/b/junfeng/archive/2005/02/12/371683.as...](http://blogs.msdn.com/b/junfeng/archive/2005/02/12/371683.aspx)

~~~
ygra
Oh, didn't know that. Thank you. But it seems indeed like this scenario is
neither really advertised, nor supported by IDEs, so adoption is probably very
low.

------
junto
This is probably a stupid question, but why do we have null as a concept?
Nullable booleans especially grate on me. Surely it is true or false, but not
null. Otherwise you surely have the wrong type? Does anyone else have these
deep down feeling that null feels wrong?

~~~
jasode
_> Surely it is true or false, but not null._

If that's surely what you have, then you have a regular "bool" and not
nullable "bool?".

In C#, "bool" and "bool?" are _not the same type_. (Although C# provides some
convenient implicit conversions that minimize tedious verbosity when working
with both -- but that convenience also has the effect of blurring the lines.
Nevertheless, they are different types.)

A "bool" can represent 2-states. A "bool?" can represent 3-states: true -or-
false -or- unknown/empty/indeterminate/invalid/etc.

Your premise that I quoted is _constrained_ to 2 states -- therefore use the
2-state type which is plain "bool". Unless you think nullable "bool?" as a
syntax seems to defy some kind of airtight mathematical logic? What would be
the alternative?!? Have everyone create a custom enum that with 3 enum values
"{falsy = 0; truthy = 1; unknown = 2}"? Why would reinvention of those
semantics in everyone's redundant code snippets be better than C#'s standard
nullable "bool?"?

(Another issue that may confuse the "null" discussion is the 2 separate
concepts of "null": #1 is "null" as an indicator of pointing to invalid memory
and #2 is "null" as _deliberate semantic_ placeholders for
application/business logic of _unknown values_. The #2 concept is what is
modeled by C# nullable<T> and SQL database fields.)

~~~
CuriousSkeptic
This view isn't without criticism though.
[http://www.alternativetech.com/publications/copper.pdf](http://www.alternativetech.com/publications/copper.pdf)

Edit: "Logicians have proved that a large class of MVLs are not truth-
functionally complete[.] They have also proved that if such an MVL is made
complete (for instance, by adding the Slupecki T-function), it becomes
inconsistent! Therefore[,] we can have either truth-functional completeness or
consistency, but not both."

~~~
jasode
The last time I looked at this, most of the arguments were focused on
mathematical rigor of comparing NULL to NULL. Are they the equal or not? (The
RDBMS of Oracle, MSSQL, etc don't all agree.) It doesn't matter which
interpretation one favors, it will eventually lead to a logical contradiction.

If you took away the Nullable<T> concept to conveniently add 3-value logic to
value types, _the same philosophical problem still remains_. If you force
programmers to manually reinvent their own 3-value logic (e.g. manually add in
an extra bool variable "HasValue" to signify whether _another variable 's_
content is "valid", _you still have the same conceptual problem_ your pdf is
grappling with.

~~~
CuriousSkeptic
I was merely adding context.

The arguments mostly boils down to

\- the mathematical rigor, as you suggest, which besides the issue of
contradictions also introduces problems for the implentattion of things like
query optimization.

\- non-null solutions are possible, f.ex. normalization, which besids avoiding
the null-issue also comes with other benefits.

However, I'm not sure Nullable<T>, is problematic in the same sense. It is,
after all, an explicit value domain, and not part of any logic at all. Notice
how the debate about relational systems doesn't talk of a Boolean value domain
(MSSQL doesn't even have a Boolean type, only a single bit number type) but of
the predicate logic resulting from existing and non-existing rows.

I guess a comparable situation would rather be, if you have a Nullable<T>
where T:class, how do you treat the difference between boxed and unboxed
nulls?

In, Scala, f.ex., it's perfectly valid to have Some(null) != None, which means
you need to handle the null value even for non-None values.

------
jug
I always liked Swift for the pragmatic solution to null reference issues,
perhaps the most attractive aspect of that language to me, so this is nice to
see!

