Non-nullable reference types in C#
C# 1.0 has non-nullable value types (an int variable must always have a valid int value, it cannot be null) and nullable reference types (a string variable can be null). C# 2.0 added nullable value types (an int? variable - note the "?" - can be null). There are unfortunately no non-nullable reference types (a string variable which can never be null). Patrick Smacchia has a summary of a possible notation and also of the issues that could appear.
However, until Microsoft decides to add non-nullable reference types, there's a way of doing the same thing with a somewhat more complicated notation.
A method enforcing a not-null argument would look like this:
and would be called like this:
Incidentally, this notation also serves as a form of specification - this parameter should not be null. I was thinking of using attributes but I think it would lead to a more verbose notation in case of several non-nullable parameters. I hope this helps someone :)
However, until Microsoft decides to add non-nullable reference types, there's a way of doing the same thing with a somewhat more complicated notation.
- using System;
- namespace Extensions
- {
- public struct NotNull<T> where T : class
- {
- public readonly T value;
- public NotNull(T arg)
- {
- if (arg == null)
- throw new ArgumentNullException("arg");
- value = arg;
- }
- // convert non-nullable to regular
- public static implicit operator T(NotNull<T> arg)
- {
- return arg.value;
- }
- // convert regular to non-nullable
- public static implicit operator NotNull<T>(T arg)
- {
- return new NotNull<T>(arg);
- }
- // explicit cast to non-nullable -- needed when T == object
- public static NotNull<object> Cast(object arg)
- {
- return new NotNull<object>(arg);
- }
- public override string ToString()
- {
- return value.ToString();
- }
- public override bool Equals(object obj)
- {
- return value.Equals(obj);
- }
- public override int GetHashCode()
- {
- return value.GetHashCode();
- }
- public static bool operator ==(NotNull<T> left, NotNull<T> right)
- {
- return Equals(left, right);
- }
- public static bool operator !=(NotNull<T> left, NotNull<T> right)
- {
- return !Equals(left, right);
- }
- }
- }
A method enforcing a not-null argument would look like this:
- public string Test(NotNull<string> s)
- {
- string ss = s;
- return ss.Substring(0); // no need to test for null
- }
and would be called like this:
- public void TestNotNull()
- {
- string s;
- s = "something";
- Test(s);
- s = null;
- Test(s);
- }
Incidentally, this notation also serves as a form of specification - this parameter should not be null. I was thinking of using attributes but I think it would lead to a more verbose notation in case of several non-nullable parameters. I hope this helps someone :)
Comments
otherwise you have allowed a direct pass of null:
public void TestNotNull()
{
string s;
s = "something";
Test(s);
s = null;
Test(s); <- Fails on enter
Test(null); <- Fails inside method.
}
using a struct would make it fail up front as intented.
[Test]
public void testOperatorBoolEquals()
{
NotNull string obj = "some text";
NotNull string obj2 = "some text";
Assert.IsTrue(obj == obj2);
}
it's will be work with this changes
public static bool operator ==(NotNull T left, NotNull T right)
{
return Equals(left.value, right.value);
}
public static bool operator !=(NotNull T left, NotNull T right)
{
return !Equals(left.value, right.value);
}
Test( new NotNull<string>() );
You're right to use a readonly field to store the reference however you should make it private and return the reference through a property that (additionally) checks for null before returning.