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