Non-nullability in C# 8.0 and F#

by Marc 10. September 2017 22:46

Once in the past, I was wondering how many times I had written null checks in C# so far. It must have been at least ten thousand times. Later, I discovered F#, which avoids null in most cases. Seeing that "in principle, it can be done in .NET languages", I wrote a Visual Studio User Voice suggestion to add compile-time null reference checking to C#. The suggestion quickly rose to the top and stayed there until today.

Finally... Six years and four versions later, non-nullability will be introduced with C# 8.0. And the waiting was worth it! The C# design team found an intuitive, non-intrusive solution, which fits seamlessly into the existing syntax. What's more, the C# 8.0 approach goes even farther, and arguably is safer, than the F# approach!

Feature C# 8.0 F#
Class declaration class SafeFoo { } type SafeFoo = class end
- [<AllowNullLiteral>]
type UnsafeFoo = class end
Binding declaration SafeFoo safefoo; val safeFoo : SafeFoo
// New in C# 8: Nullability must be
// explicitly declared with ?
SafeFoo? unsafeFoo;
-
- val unsafeFoo : UnsafeFoo
Binding null unsafeFoo = null; unsafeFoo = null
// Compiler warning
safeFoo = null;
// Compiler error
safeFoo = null
// Compiler warning via flow analysis
safeFoo = potentiallyGetNull();
// No compiler warning
safeFoo = potentiallyGetNull()
// Either check for null with if..., or
// use C# 8 "dammit" operator
// when you're sure it's not null:
safeFoo = potentiallyGetNull()!;
-
Dereferencing nullable // Compiler warning via flow analysis
unsafeFoo.Bar;
// No compiler warning
unsafeFoo.Bar
// Either check for null with if..., or
// use C# 2 null-coalescing operator
unsafeFoo new Foo()
-
// or use C# 6 null-conditional operator
unsafeFoo?.Bar
-
// or use C# 8 "dammit" operator
// when you're sure it's not null.
unsafeFoo!.Bar
-

Some of the differences between C# 8.0 and F# are:

  • In F#, only types defined in F# are non-nullable. In C# 8.0, all types are non-nullable, regardless of the language in which they have been defined.
  • In F#, you have to decide already at the type definition level whether bindings of the type can be nullable. If a type is declared nullable, then all of its bindings are nullable without exemption. By contrast, in C#, all bindings of all types are non-nullable by default, and nullablilty can only be allowed for one binding at a time.
  • When you introduce a nullable binding in C#, flow analysis will consequencly enforce null checks. Nothing like that exists in F#. (Although, at least with regards to type inference, F#'s static program analysis is more advanced than C#'s).

To be fair, nullability is viewed from a different perspective in C# and F#. In C#, if you want a value to be optional, you typically do this by allowing null. At the same time, null is also used to signal that a variable has not been completely initialized yet. The concerns of optionality and initialization state are not separated at the language level, which is inelegant.

In F#, if a value is meant to be optional, you use the built-in F# type Option<T>. Furthermore, F# is an expression-based language from the ground up. The expressive power enables a programming style where variables (called bindings in F#) can have only one state, which is completely initialized and immutable from the beginning. In such an environment, there is no need for null at all.

The reason null exists in F# is to be compatible with the CLI and other .NET languages. And here things get a little convoluted. Even when you program only in F#, you always have to deal with non-F# types, e.g., System.String. Bindings of non-F# types are allowed to be null in F#, which can lead to bizarre constellations such as let s : string option = Some null.

Ironically, C# 8.0 will give you the foundation to define your own, custom Option<T> type that is even more safe than F#'s built-in one (by avoiding the "Some null" problem). But there's no reason for doing that. Better keep it simple and stick with the new features of the C# 8.0 compiler.

More information on C# 8.0's planned nullability features can be found here:

Tags:

.NET Framework | C# | F#

Calculating a range of arbitrarily large prime numbers in F# 2.0

by Marc 15. November 2010 20:30

The library System.Numerics.dll, who was introduced in .Net 4.0, contains a System.Numerics.BigInteger structure. BigInteger represents a whole number of arbitrary size (or precision). Before .Net 4.0, the largest number that could be represented "out of the box" was System.Double.MaxValue. Written in decimal notation, this would be a whole number with 309 digits (more than 179 thousand centillion). However, using Double for whole number calculations is error-prone. Double is internally stored with floating point logic; the larger the number, the less exact it becomes. For instance, you cannot exactly represent the number ten quadrillion (i.e., ten million billion):

let x = 1.0e+16
let y = x - 1.0
printf "%b" (x = y)
// Prints true! 

Through the introduction of System.Numerics.BigInteger, it is now possible for any .Net Framework language to exactly represent any whole number whatsoever. In the following example, we will use this type to implement a function that calculates a range of arbitrarily large prime numbers. We will design it as a static library method which can be called by any .Net 4.0 client application. The signature, seen from C#, should be as follows:

Desired Signature, as Seen From C#

using System.Collections.Generic;
using System.Numerics;

namespace MyCompany.MyProduct{
    public static class BigMath{
        public static IEnumerable<BigInteger> 
        PrimesBetween(BigInteger i, BigInteger j){
            // etc.

Implementation in F#

To implement the library method, proceed as follows:

  • (If not done yet: Install the F# Power Pack)
  • Create a new F# class library project
  • Set the .Net Framework 4 client profile as the compilation target
  • Add references to System.Numerics.dll and FSharp.PowerPack.dll
  • Add a new source file BigMath.fs with the following code:
/// Provides static methods for mathematical functions involving 
/// arbitrarily large numbers. 
module MyCompany.MyProduct.BigMath

/// <summary>Gets a lazily evaluated sequence of prime numbers.</summary>
/// <param name="i">The beginning of the interval for the prime numbers.</param>
/// <param name="j">The end of the interval for the prime numbers.</param>
/// <returns>
/// A sequence with the prime numbers between <paramref name="i"/> 
/// and <paramref name="j"/>.
/// </returns>
let PrimesBetween(i, j) =
    /// Approximates the square root of a BigInteger with a 
    /// BigRational, according to the "babylonian method". 
    let sqrtI i =
        let iN = BigRational.FromBigInt i
        let half n = n / 2N
        let rec approachWith n =
            let diff = BigRational.PowN(n, 2) - iN
            if diff >= 0N && diff < 1N then n
            else approachWith(half(n + iN / n))
        approachWith(half iN)

    /// Gets true if i can be divided by a number >= 2,
    /// where i is a non-negative BigInteger.
    let hasDivisor i =
        let maxDiv = 
            let sr = sqrtI i
            min (sr.Numerator / sr.Denominator + 1I) (i - 1I)
        let rec hasDiv div =
            if div > maxDiv then false
            elif i % div = 0I then true
            else hasDiv(div + 1I)
        hasDiv 2I   

    /// Gets true if i is a prime number. 
    let isPrime i =
        match i with
        | _ when i < 2I -> false
        | _ when i = 2I -> true
        | _ -> not (hasDivisor i)

    /// The sequence of numbers between i and j.
    let range =
        let step = i |> compare j
        match step with
        | 0 -> Seq.singleton i
        | _ -> seq {i .. bigint step .. j}

    /// The resulting sequence of prime numbers between i and j.
    range |> Seq.filter isPrime  

Usage from C#

The compiled F# library can be used from C# as follows:

// using System;
// using MyCompany.MyProduct;
var primes = BigMath.PrimesBetween(10000200, 10000150);
foreach (var p in primes)
    Console.WriteLine(p.ToString("#,#"));
// Produces:
// 10,000,189
// 10,000,169

Concluding Remarks

The parameters of the PrimesBetween function are declared in tupled (not curried) form, which corresponds to par. 4.2 "Object and Member Design" of the F# Component Design Guidelines, which says "Do not use currying of parameters in vanilla .NET APIs".

All recursive functions are implemented tail recursively, using accumulator arguments, so that no stack overflow will ever occur.

The result is a strongly typed generic enumerable of BigInteger. At any given time, no more than one prime number is held in memory, regardless of the size of the interval between i and j.

The square root calculation in the sqrtI function is an optimization. To know whether a number has a divisor, it is sufficient to try division by all numbers between 2 and the square root. For the calculation of the square root, we use the type Microsoft.FSharp.Math.BigRational from FSharp.PowerPack.dll.

To calculate extremely large prime numbers in a productive situation, we would have to speed up the function using a cache. Perhaps unexpectedly, this cache would not necessarily store the resulting prime numbers. Instead, it would be gradually built with all prime numbers from the bottom up, starting at 2, whenever the recursive hasDiv function is called. The hasDiv function would then be modified to no more try out all whole numbers starting from 2 as potential divisors, but only all (recursively cached) primary numbers starting from 2, which is sufficient. This would enormously reduce the amount of divisions. The next step would then be to persist the cache in a database. The resulting library could be run for many years, returning larger and larger prime numbers, until (presumably) the currently calculated BigInteger number would be so large as to overstrain the system memory. I leave it up to you to speculate approximately when this might happen...

Prerequisites for implementing a keep-alive mechanism in WCF 3.0

by Marc 7. March 2010 00:59

There seems to be a common misconception that, in order to find out whether a WCF session is still alive, one has to implement some kind of custom ping or heartbeat operation on the service, which is to be regularly called by the client application. However, the WCF framework, when configured correctly, already does this for you in the background.

The key to this feature is the ReliableSession class. When ReliableSession.Enabled is true, WCF will continuously generate internal infrastructure messages to check whether the service is still ready. After the service has been dead for some specified time, the proxy's ClientBase<TChannel>.State is automatically set to CommunicationState.Faulted, and the ICommunicationObject.Faulted event is raised, giving the client application a chance to react. The delay between the service breakdown and the Faulted event can be specified through the ReliableSession.InactivityTimeout. If, for instance, the InactivityTimeout is set to four minutes, WCF will generate several infrastructure messages during every four minutes. Therefore, if you shut down the service, the Faulted event will be raised on the client after four to six minutes. If you set the InactivityTimeout to 20 seconds, it will be raised after 20 to 30 seconds. The exact duration depends on WCF-internal implementation details.

In order for this to work, you also have to set the Binding.ReceiveTimeout to at least the duration of the InactivityTimeout. The ReceiveTimeout specifies how long the service will stay alive without any service operations being called from the client application. If, for instance, you expect your client application to call service operations at least twice an hour, you may set the ReceiveTimeout to 30 minutes, but still let the InactivityTimeout be 4 minutes or so, in order that the client application can take measures in the background when the service is temporarily interrupted.

The following example shows how to define both timeouts on the client and server sides, either configuratively (in the App.config file) or imperatively (in code). The example presupposes that you are using a reliable session-capable binding (such as WSHttpBinding or NetTcpBinding), and that you have applied the ServiceContractAttribute.SessionMode, ServiceBehaviorAttribute.InstanceContextMode, OperationContractAttribute.IsInitiating, and OperationContractAttribute.IsTerminating properties in meaningful ways. If you are not sure about that, you may want to read the respective MSDN documentation entries first. A comparison table of the system-provided bindings can be found here. Furthermore, if you do not like hand-coding configuration files, you can use the WCF service Configuration Editor Tool, which is installed with the Microsoft Windows SDK.

Defining the Timeouts Configuratively

<configuration>
  <
system.serviceModel>

    <!--
In the App.config files of the service host and client apps: -->
    <
bindings>
      <
netTcpBinding>
        <
binding name="myNetTcpBinding" receiveTimeout="00:30:00">
          <
reliableSession enabled="true" inactivityTimeout="00:04:00"/>
        </
binding>
      </
netTcpBinding>
    </
bindings>

    <!--
In the App.Config file of the service host app: -->
    <
services>
      <
service name="MyTest.MyService">
        <
endpoint
        
address="net.tcp://localhost/MyService/"
        
binding="netTcpBinding"
        
bindingConfiguration="myNetTcpBinding"
        
contract="MyTest.IMyService"/>
      </
service>
    </
services>

    <!--
In the App.Config file of the client app: -->
    <
client>
      <
endpoint
      
address="net.tcp://localhost/MyService/"
      
binding="netTcpBinding"
      
bindingConfiguration="myNetTcpBinding"
      
contract="MyTest.IMyService"/>
    </
client>

  </
system.serviceModel>
</
configuration>

Defining the Timeouts Imperatively

// using System;
// using System.ServiceModel;

// In the service host and client apps:

var
myNetTcpBinding = new NetTcpBinding();
myNetTcpBinding.ReceiveTimeout = new TimeSpan(0, 30, 0);
myNetTcpBinding.ReliableSession.Enabled = true;
myNetTcpBinding.ReliableSession.InactivityTimeout = new TimeSpan(0, 4, 0);

// In the service host app:
var
host = new ServiceHost(typeof(MyService));
host.AddServiceEndpoint(typeof(IMyService), myNetTcpBinding, "net.tcp://localhost/MyService");

// In the client app:
var
factory = new ChannelFactory<IMyService>(myNetTcpBinding, "net.tcp://localhost/MyService");
var 
channel = factory.CreateChannel();

Book review: Pro WPF in C# 2008

by Marc 27. February 2010 17:55
Book image Title: Pro WPF in C# 2008
Subtitle: Windows Presentation Foundation with .NET 3.5, Second Edition
Publisher: Apress® Books for Professionals by Professionals™
Series: The Expert's Voice in .NET
Author: Matthew MacDonald
Date of appearance: February, 2008 (1040 Pages)

This book is a thorough examination of the WPF 3.5 technology – its architecture, what you can do with it, and how to do it. It is directed at professional C# developers.

The book is written in a systematic, comprehensible way. A chapter starts with a basic introduction and includes graphics of the respective WPF sub-class hierarchy. The chapter's subject is then steadily explored in more and more detail. For instance, at the beginning, there are five pages just on resolution independence. XAML is explained in-depth, starting with the four ways of loading and compiling: Code-only, code and uncompiled XAML, code and compiled XAML, and XAML only; this is followed by the specifics of the XAML grammar (markup extensions, attached properties, etc.). There are seven pages on non-rectangular windows and sixteen pages on playing sound on different OS versions. As the book goes on, the author really shines in describing complex subjects, such as 3-D drawing, in a logically understandable way. Towards the end, there is a tabular overview of features missing in WPF compared to Windows Forms, with recommendations on when to choose one over the other, or both of them together, and how to mix them best.

The volume also contains lots of small, but precious pieces of surplus information, such as: Properties of WPF controls can be set in any order, without causing any change in behavior; or: By using an overloaded version of DependencyObject.SetValue in code, you can attach a value for any dependency property, even if it is not defined as an attached property (which is not possible in XAML). In addition, the author mentions various quirks of WPF, and how to get around them, if possible. Example: When you restart an animation that is almost complete, and the animation had the current position as the starting point, the animation will appear to slow down. Another example: Windows Vista always requires permission elevation for a setup, even though, in the case of Click Once, this makes no sense. As a consequence, a Click Once WPF application, on Vista, cannot be installed under a regular user account; the user is forced to install it under an admin account - which defeats the purpose of using Click Once in the first place...

Developers are all-too-familiar with the Pareto principle: 80% of the tasks of a project can be solved „easily“ in 20% of the time, but solving the other 20% takes at least 80% of the time. If you want to use WPF in a productive way, I strongly recommend taking the time to study this book. Admittedly, at 1040 pages, this is quite some endeavor. However, you will be rewarded many times over, as you will be saved a lot of frustration and unexpected delays, when you already know from the beginning how to solve much of the other 20%.

Month List