• my name (unregistered)

    Tern Around Bright eyes

  • Prime Mover (unregistered)

    And I was expecting someone to have mis-spelt "ternary" somewhere in the post.

    No, just lack of attention to detail.

  • Sole Purpose Of Visit (unregistered)

    Just out of interest, Remy, when you say you prefer optional types, do you mean actual optional types (eg Haskell's Maybe) or simply a nullable native type?

    I'm asking because I'm trying to steer cow-orkers (oops, a pun) towards Maybe in C#. It's hard work to wean people off nulls.

  • Brian (unregistered) in reply to Sole Purpose Of Visit

    Not Remy, but this is something I've also been dealing with lately. Personally, I've found nullable reference types in C# to be quite useful (by which I mean annoying enough to push people to resolve the nulls as early as possible and then use non-nullable refs from then on), assuming you're using a version of the language that supports that feature.

  • (author) in reply to Sole Purpose Of Visit

    Maybe I'm not totally up on type theory, but aren't nullables just a special case of optional types? Is there some special magic that Haskell's Maybe or C++'s Optional do that the nullable doesn't? I don't think there is. In C#, nullables are implemented basically the same way- Nullable<T> as a wrapper class around some object which might be null. C# just chucks a bunch of syntatic sugar in there to make it read better.

  • Brian (unregistered)

    This article's (headline) is for the burds.

  • Kythyria (unregistered) in reply to Remy Porter

    Nullable is pretty much Option/Maybe, yes. The catch is that C# references are always able to be null unless you turn on the nullability annotations, a fact that makes all of this less useful, and probably why Nullable was originally introduced to work only on value types.

    C# also didn't let you say if(Foo.HasValue(out var v)) at the time, which helps the ergonomics a lot.

  • Sole Purpose Of Visit (unregistered) in reply to Remy Porter

    Maybe (or Optional in some language libraries) can be considered as a wrapper for a value, rather than a directly nullable type. (It's actually an applicative functor, but who cares? The only thing you need to know is that you need to bind to something to get the value out.)

    You can work directly with a nullable type in C#:

                        double? fred = null;
                        if (fred == 1)
                        {
                            System.Console.WriteLine(fred);
                        }
    

    ... but that isn't really much of an improvement on a naked null. In this case you will get a null exception. If you use a Maybe and it binds to an if/else (ie it doesn't allow you to deal with the wrapped value directly) then you force the consumer to consider the possibility that the wrapped value is null.

    At least, that's the way it works in my implementation. Ideally you would use it in SelectMany for ILists (there is an implementation in GitHub), but that's only really useful if everything you deal with is an IList.

  • Sole Purpose Of Visit (unregistered) in reply to Remy Porter

    Then again, Nullable<T> appears to be pretty much the same thing. Except that it's only available in 8.0, and it needs to be switched on, and I haven't used it, but as far as I can see you get a compiler warning rather than being forced to bind to the underlying value.

  • gordinfish (unregistered)

    Laughs in named parameters.

    I'm rather surprised that no one has brought that up, as they are far superior in a lot of ways to ye olde positional arguments.

  • Kythyria (unregistered) in reply to Remy Porter

    I should probably also point out that Rust and Haskell make Option/Maybe out of sum types (ie, "a Foo can be a Bar, Baz, or Quux", where any of those things can be just the name or include some data). So a bunch of ergonomics and implementation details comes from how the language handles those.

    In particular, an Option-al reference (in a lang where references are never null) may well be implemented as a nullable reference (normally sum types are done as tagged unions). And pattern matching and destructuring assignment can be used to get at the inner value.

  • (author) in reply to Sole Purpose Of Visit

    Code like that doesn't trigger an exception.

      static void Main() {
          double? fred = null;
        if (fred == 1)
        {
            System.Console.WriteLine(fred);
        }
        Console.WriteLine("This is fine.");
      }
    }
    

    Prints "This is fine". Because the nullable operator is just a bit of syntatic sugar around Nullable<double>, so fred does have a value and is not a null reference- the contents of fred are null. Similarly, if you did fred?.ToString() that's actually going through the Nullable wrapper and just hiding the details from the developer.

    And I'm not sure what you mean about Version 8- Nullable<T> has been in .NET since .NET 2.0: https://learn.microsoft.com/en-us/dotnet/api/system.nullable-1?view=net-7.0#applies-to

    (There's a debate to be had about if that syntatic sugar actually makes the language better- more ergonomic, yes, but if you look at the Linq query syntax, you can see lots of opportunity for confusion because the code you write is nothing like what the compiler sees)

  • NoLand (unregistered)

    Be sure to keep your nulls fresh. Stale nulls are the primary cause of null pointer exceptions! ;-)

  • (nodebb) in reply to Sole Purpose Of Visit
    Comment held for moderation.
  • (nodebb) in reply to Remy Porter

    Hehe, you shouldn't say your "bit of syntatic sugar" when someone of the .net language team is around. After all they had to complete respec the CTS to allow a value type be assigned null, changed the compiler accordingly and did a lot of magic to make everything work a smoothly as it is.

    After all, nullable value types in C# are not reference types, they are value types boxing the value type with an additional boolean member.

  • (nodebb) in reply to Sole Purpose Of Visit
    Comment held for moderation.
  • Sole Purpose Of Visit (unregistered) in reply to Remy Porter
    Comment held for moderation.
  • (nodebb)

    Technically, this code is "terning" nulls into nulls, not values.

  • (nodebb)

    NULL, the worst thing ever created. Except all of the alternatives were worse.

  • Kythyria (unregistered) in reply to TheCPUWizard

    Whether nullptr is better or worse than the alternatives seems to depend on whether said alternatives are retrofitted and how they work. Sum types work really well, with the right support, but if you staple any replacement for null on after the fact rather than have them from the start, there'll be lots of places that shouldn't be nullable but aren't declared null-free.

    The refactoring to add that declaration is frequently easy, there's just a lot of it, and inevitably external libs will be unfixable.

  • Craig (unregistered) in reply to Remy Porter
    Comment held for moderation.

Leave a comment on “Terning Nulls into Values”

Log In or post as a guest

Replying to comment #:

« Return to Article