Nullable!T

Adam Ruppe destructionator at gmail.com
Tue Jul 6 06:25:36 PDT 2010


On 7/6/10, bearophile <bearophileHUGS at lycos.com> wrote:
> 1) Nullable!(SomeClass) is forbidden in C#.

I figure a Nullable struct would just alias the original type if T t;
t = null; already compiles. So a nullable pointer, class, or Nullable
is just a no-op. This would cover your cases 1 and 2 with a simple
rule.

> Optionally this can be accepted:
> Nullable!int x;
> if (x) { ...
> that is equivalent to:
> if (x.hasValue) { ...
> But this doesn't look fully tidy to me...

Blargh, what I'd want is

if(x is null)


An implementation that might work is

=============

template Nullable(T) {
	static if(is(typeof( {
		T t;
		t = null;
	}))) {
		alias T Nullable; // if it is already nullable, do nothing special
	}
	else
	{
		struct Nullable {
			T value;
			T* hasValue = null; // i guess this could be boolean too

			bool opCast(A)() if(is(A == bool)) { // for if(x)
				return !(hasValue is null);
			}

			typeof(this) opAssign(T v) { // should be ok assigning known not-null values
				value = v;
				hasValue = &value;
				return this;
			}

			typeof(this) opAssign(typeof(this) t) { // Nullable!T = Nullable!T
should always be good
				value = t.value;
				if(t.hasValue)
					hasValue = &value;
				else
					hasValue = null;
				return this;
			}

			typeof(this) opAssign(void* nullptr) { // so literal null assignment works
				assert(nullptr is null);
				hasValue = null;
				return this;
			}
		}
	}
}

// below is a kind of unittest

class A {}

import std.stdio;

void main() {
	A a1;
	Nullable!A a2;

	a1 = a2;
	a2 = a1; // compatible; types are aliases

	Nullable!(Nullable!A) a3;

	a1 = a3; // still compatible, aliases

	int* b1;
	Nullable!(int*) b2;

	b1 = b2;
	b2 = b1; // aliases again

	int c1;
	Nullable!(int) c2;

	assert(!c2.hasValue); // it should start null

	//c1 = c2; // doesn't compile; they are different types
	c2 = c1; // does compile, and set to non-null implicitly

	assert(c2.hasValue); // just assigned to it; shouldn't be bull

	c2 = null; // should compile, set to null

	assert(!c2.hasValue);

	Nullable!(Nullable!int) c3;

	c3 = 10; // should be fine

	c2 = c3; // should compile

//	c1 = c3; // should not and does not

	if(c2) // same as if(c2.hasValue)
		assert(0);
	else
		writefln("value is %d", c2.value);
}

==============



> C# has the ?? operator (Elvis operator) that can be used to replace this:
> int y = x ?? -1;

Meh, the regular ternary works fine, or this could be a member function:

x.get(-1); // gets if not null, returns -1 if it is null

x itself is a struct, so it can never be null, so no need to worry
about x.get throwing a segfault.


> This can be done in D too, but this can be added later too. The advantage of
> this syntax sugar is to encourage programmers to use Nullables.

Gah, Nullable!T is perfectly fine. I don't even know if you actually
want to encourage people to use nullables; they shouldn't be needed
all that often says my gut. Better to avoid things being null if
possible.


More information about the Digitalmars-d mailing list