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