[Mono-dev] Lang Theory Question

Scott Peterson lunchtimemama at gmail.com
Fri Feb 1 20:56:47 EST 2008


I'm a sucker for syntactic sugar. There is one little trick which I've
been trying and failing to do - it turns about to be impossible - but
as a language theory exercise, I thought I'd work out what would be
needed to let me do this thing.

One nice thing about nullable types is the non-standard behavior of
the assignment (=) operator. For example:

int? val = 5;
val = 6;

is shorthand for:

Nullable<int> val = new Nullable<int> (5);
val.Value = 6;

I am working with a struc similar to Nullable and I'd like to be able
to use the assignment operator in a similar way. Unfortunately, the
assignment (=) operator cannot be overloaded. The struct, SchemaEntry,
is used to store and retrieve configuration data from some backend
(gconf, the Windows registry, an XML file, &c.). Here's essentially
how I currently use the struct:

SchemaEntry<int> entry = new SchemaEntry<int> ("DbVersion");
int version = entry.Get ();
if (version < 2) {
    MigrateDb ();
    entry.Set (2);
}

I would like to be able to do the above with this code:

SchemaEntry<int> entry = new SchemaEntry<int> ("DbVersion");
int version = entry;
if (version < 2) {
    MigrateDb ();
    entry = 2;
}

This is how I envision writing the code to allow me to do that:

public struct SchemaEntry<T>
{
    public SchemaEntry (string name)
    {
        //...
    }

    //...

    public static SchemaEntry<T> operator =(SchemaEntry<T> entry, T value)
    {
        entry.Set (value);
        return entry;
    }

    public static implicit operator T (SchemaEntry<T> entry)
    {
        return entry.Get ();
    }
}

This is obviously not possible because C# forbids overloading =. A
potential problem is as follows:

SchemaEntry<int> entry = 5;

As you can see in the outline of SchemaEntry above, there is no
parameterless constructor, so this code is clearly problematic. One
solution to treat this as:

SchemaEntry<int> entry.Set(5);

and throw a "use of unassigned variable" compiler error. If you wanted
to allow this syntax (in the way that Nullable uses this syntax), you
could allow for overloading of the "new" operator like so:

public static Nullable<T> operator new(T value)
{
    return new Nullable<T>(value);
}

Another problem is allowing overloading assignment between the same type:

public class Foo
{
    public static Foo operator =(Foo f1, Foo f2)
    {
        f1 = f2; // recursive fail
    }
}

I can think of a few possible solutions:
1) Require that the two parameters to the overload function be of
different types. This would still allow the safe use of generics (as
with SchemaEntry).
2) Stipulate that any use of the assignment operator inside of an
assignment operator overload function will perform a standard bitwise
copy.
3) I had other solutions, but I actually think these two cover it pretty nicely.

I prefer solution 1. I've given it a little think and no problems jump
out at me. So I post this to solicit counter cases. If you'd like to
tell me that this kind of syntax is a) confusing, b) unnecessary, c)
evil, d) all of the above, have at me, but I am more interested in
disastrous corner case in my above proposal. And if you too yearn to
save yourself precious parenthesis, feel free to chime in too!

-- 
Scott.



More information about the Mono-devel-list mailing list