What’s Different in the Revised Language Definition?

Declaring Indexed Properties

 

 

In an earlier entry on operator overloading, I showed the following construction, in which the x-coordinate of a managed reference Vector class object is directly accessed using an indexed property, as follows:

 

int main()

{

       Vector^ p2 = gcnew Vector( 1.475 );

       Vector^ p3 = gcnew Vector( p2[ 0 ], 2.4745 );

}

 

If you are not familiar with the original language, you will be as surprised as I was to discover that this construct is not supported. That is, all indexed properties are required to be given a name, and there is therefore no way, for example, to provide a managed subscript operator that can be directly applied to a Vector or Matrix class object. This is something of a fatal wound to the language if you care about subscripting. A second lexical shortcoming is that it is visually difficult to distinguish between a property declaration from that of an indexed property – the number of parameters is the only indication. Finally, indexed properties suffer from the same problems as those of scalar properties – the accessors are not treated as an atomic unit, but separated into individual methods.  For example,

 

public __gc class Vector;

public __gc class Matrix

{

    float mat[,];

 

public:

   __property void set_Item( int r, int c, float value);

   __property int get_Item( int r, int c );

 

   __property void set_Row( int r, Vector* value );

   __property int get_Row( int r );

};

 

As you can see, the indexers are distinguished only by the additional parameters to specify a two or single dimension index. In the revised syntax, the indexers are distinguished by a bracket following the name of the indexer and within which are listed the index types and optional index identifiers. In addition, as with the scalar properties, the get/set accessors are collected within a brace pair. For example,

 

public ref class Vector;

public ref class Matrix

{

private:

      array<float, 2>^ mat;

 

public:

 

      property int Item [int,int]

      {

            int get( int r, int c );

            void set( int r, int c, float value );

      }

 

      property int Row [int]

      {

            int get( int r );

            void set( int r, Vector^ value );

      }

 

};

 

The design question with regard supporting a class level index property is in how to indicate that the index applies to the class itself? There is no one solution to this. One suggestion was to use the class name, analogous to the declaration of a constructor. A second suggestion championed the this keyword. And the winner is: default. To specify a class level indexed property, one substitutes the default keyword for the user-specified name. For example,

 

public ref class Matrix

{

private:

      array<float, 2>^ mat;

 

public:

 

      // ok: class level indexer now

      //

      //     Matrix mat …

      //     mat[ 0, 0 ] = 1;

      //

      // invokes the set accessor of the default indexer …

 

      property int default [int,int]

      {

            int get( int r, int c );

            void set( int r, int c, float value );

      }

 

      property int Row [int]

      {

            int get( int r );

            void set( int r, Vector^ value );

      }

 

};

 

Some C++ programmers have expressed unhappiness with the factoring out of subscript support into the separate index facility. What’s wrong, they ask, with using the standard operator []? The primary difficulty of the subscript operator is that it is very challenging to distinguish between a read and write operation whereas it comes for free in the index property.

 

 

disclaimer: This posting is provided "AS IS" with no warranties, and confers no rights.