Using unary expressions with property functions

Jonathan M Davis jmdavisProg at gmx.com
Mon Dec 13 11:29:34 PST 2010


On Monday, December 13, 2010 11:10:55 Andrej Mitrovic wrote:
> So I was a bit surprised today to find out that this sample C# code works:
> 
> class LibraryItem
> {
>     private int _numCopies;
> 
>     // Property
>     public int NumCopies
>     {
>         get { return _numCopies; }
>         set { _numCopies = value; }
>     }
> 
>     public void BorrowItem(string name)
>     {
>         NumCopies--;
>     }
> }
> 
> Apparently you can use the -- and ++ unary ops on property functions, which
> might be convenient, I guess. But this won't work in D:
> 
> class LibraryItem
> {
>     private int _numCopies;
> 
>     @property
>     int NumCopies()
>     {
>         return _numCopies;
>     }
> 
>     @property
>     void NumCopies(int value)
>     {
>         _numCopies = value;
>     }
> 
>     public void BorrowItem(string name)
>     {
>         NumCopies--;
>     }
> }
> 
> void main()
> {
> }
> 
> I get this back: Error: this.NumCopies() is not an lvalue
> 
> So D tries to call the getter method "int NumCopies()" and apply -- on it.
> One way around this is to make the getter method return by reference:
> 
> import std.stdio;
> 
> class LibraryItem
> {
>     private int _numCopies;
> 
>     @property
>     ref int NumCopies()
>     {
>         return _numCopies;
>     }
> 
>     @property
>     void NumCopies(int value)
>     {
>         _numCopies = value;
>     }
> 
>     public void BorrowItem(string name)
>     {
>         NumCopies--;
>         writeln(NumCopies);     // writes -1 after the call
>     }
> }
> 
> void main()
> {
>     auto lib = new LibraryItem();
>     lib.BorrowItem("TDPL");
> }
> 
> So this works. But now the getter method acts both as a getter and a
> setter, which contradicts the idea of having separate get/set methods,
> don't you agree?
> 
> I'm not sure how C# works. Does it use the getter method and return a
> reference for the -- op like in the last D example, or does it rewrite the
> whole operation as "NumCopies(-1)"? Maybe we can have a functionality like
> that in D without having to change the getter method to return a
> reference.. What do you think?

I would think that it would be doable if something ++lib.NumCopies were lowered 
to lib.NumCopies(++lib.NumCopies()). If it were post-increment, it would then 
probably turn it into something more like this:

auto toInc = lib.NumCopies();
auto temp = toInc;
lib.NumCopies(++toInc);

Of course, given that you could use pre and post-increment in the middle of an 
expression, that could get quite a bit more complicated, and a simple lowering 
could be rather difficult, but the basic idea should still hold. I don't see why 
it couldn't be done other than that figuring out the exact way to lower it in 
order to deal with the fact that it could be in the middle of an expression 
could be a bit entertaining.

I say open an enhancement request for it. Perhaps someone else can point out why 
it would be a bad idea, but on the surface, it seems quite doable.

- Jonathan M Davis


More information about the Digitalmars-d mailing list