The new ?? and ??? operators
Reiner Pope
some at address.com
Tue Sep 25 05:33:15 PDT 2007
Max Samukha wrote:
> On Tue, 25 Sep 2007 11:39:51 +0300, "Rioshin an'Harthen"
> <rharth75 at hotmail.com> wrote:
>
>> "Janice Caron" <caron800 at googlemail.com> kirjoitti viestiss?
>> news:mailman.289.1190665392.16939.digitalmars-d at puremagic.com...
>>> On 9/24/07, Rioshin an'Harthen <rharth75 at hotmail.com> wrote:
>>>> I can't begin to count how many times I've written code like
>>>>
>>>> long id = data.GetLong("ID") ?? 0;
>>> Please could you explain what that does, as I don't speak C# and can't
>>> make any sense of it. What is the return type of GetLong()? What is
>>> the type of the variable named data?
>> Certainly. :)
>>
>> GetLong, as the name suggests, is used in this example to return a long
>> (signed 64-bit value) from the database column ID, with the current database
>> row referenced through the variable data (which, e.g. could be of type
>> MySqlDataReader). GetLong may, if the column (in the row accessed) doesn't
>> contain a value, return null, to signify this, since 0 (or any other value)
>> may be a legal value in the database.
>>
>>>> long? id = data.GetLong("ID");
>>> What does the question mark after long mean? What is the type of the
>>> variable named id? Is is "long" or "long?" ?
>> The question mark after a type name means the type is nullable: basically,
>> in addition to its normal range may contain the value null. A nullable type
>> can be built using a struct or class, and as far as I'm able to tell from
>> the standard, that's how the C# compiler creates it.
>>
>> If you wish further information on nullable types, I'd recommend reading
>> section 8.19 of the C# standard, available at
>>
>> http://www.ecma-international.org/publications/files/ECMA-ST/Ecma-334.pdf
>
>
> A bit OT. Under the hood C# nullable types are structs with an
> additional bool member. ? is just a syntactic sugar for the templated
> System.Nullable struct. Here is a quickly hacked together example of
> how nullable types could be implemented in D using templates.
>
> struct Nullable(T)
> {
> alias typeof(*this) Type;
>
> T value;
> bool isNull = true;
>
> Type opAssign(T v)
> {
> value = v;
> isNull = false;
> return *this;
> }
>
> static Type opCall(T v)
> {
> Type ret;
> ret.value = v;
> ret.isNull = false;
> return ret;
> }
>
> /*
> Hacks to allow null keyword in assignments/comparisons
> if you really want it
> */
>
> Type opAssign(void* v)
> {
> assert(v == null);
> isNull = true;
> return *this;
> }
>
> int opEquals(void* v)
> {
> assert(v == null);
> return isNull;
> }
>
> T getValueOrDefault()
> {
> return isNull ? T.init : value;
> }
>
> T ifNull(T v)
> {
> return isNull ? v : value;
> }
>
> /*
> etc.
> opImplicitCasts and struct interfaces will be useful here
> */
> }
>
> class DataReader
> {
> Nullable!(T) get(T)(char[] field)
> {
> Nullable!(T) ret;
> return ret;
> }
> }
>
> void main()
> {
> auto data = new DataReader;
>
> auto id = data.get!(long)("id");
> assert(id == null);
>
> id = 20;
> assert(id != null);
>
> id = null;
>
> // a replacement for 'long x = id ?? -1'
> long x = id.ifNull(-1);
> assert (x == -1);
> }
>
> I'm sure DB people already use something like that.
Looks good. And we can overload the bitwise OR operator to make it look
a little better (in my opinion). We just add
Nullable!(T) opOr(Nullable!(T) other)
{
return isNull ? other : Type(value);
}
T opOr(T other)
{
return isNull ? other : value;
}
to your struct, and then as a new main, we get
void main()
{
auto data = new DataReader;
auto id = data.get!(long)("id");
assert(id == null);
auto id2 = data.get!(long)("id2");
id2 = 25;
auto y = id | id2; // y is a Nullable!(T)
assert(y != null);
long x = y | -1;
assert (x == 25);
id = 20;
assert(id | id2 | -1 == 20);
}
Voila!
Unfortunately, I couldn't get short-circuiting to work via using lazy on
parameters types to opOr. This is because | is parsed
left-associatively, so that doesn't work. I wonder if some
expression-templatey work could fix this...
-- Reiner
More information about the Digitalmars-d
mailing list