Using unary expressions with property functions

Robert Jacques sandford at jhu.edu
Tue Dec 14 06:52:38 PST 2010


On Mon, 13 Dec 2010 14:29:34 -0500, Jonathan M Davis <jmdavisProg at gmx.com>  
wrote:
> 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

I know this concept has been extensively discussed before, i.e. the  
problem of a.b.c.d = 1, when b, c or d happen to be a method/property.


More information about the Digitalmars-d mailing list