|
All
the object-oriented languages support encapsulation, inheritance
and polymorphism. What is different about C# is that it supports
additional features like properties, events, indexers, delegates,
etc. That is why C# is often termed as a modern object-oriented
(OO) language. In this article we will discuss two modern
OO conceptsproperties and indexers.
Properties
Properties provide an interface for the data members of a
class. Using properties, values can be stored and retrieved
from the data members. So, what is the big deal about that?
Even methods do the same thing. What's good here is that we
can access a property as if we are accessing a data member.
Manipulating data using properties is done through get and
set accessors. In the following example we have defined a
property Size for a data member size.
class sample
{
private int size ;
public int Size
{
get
{
return size ;
}
set
{
if ( value > 10 )
Console.WriteLine ( Invalid Size ) ;
else
size = value ;
}
}
}
The get accessor is invoked when we retrieve the value of
the property, whereas the set accessor is invoked when we
assign a value to the property. For example,
sample s = new sample( ) ;
s.Size = 10 ;
int i = s.Size ;
Here, the statement s.Size = 10 would invoke the set accessor.
The value 10 would get collected in value. value is a keyword
and is an implicit parameter of the set accessor. In the set
accessor we have assigned the contents of value to the size
data member. Before that we have validated the value assigned
by the user to the property. Thus a property gives the syntactical
convenience of a data member as well as the functionality
of a method. We can write any program logic and throw exceptions
in a property. It can be overridden and can be declared with
any modifiers. The statement int i = s.Size would invoke the
get accessor which returns the value of the size data member.
The returned value would get collected in i.
Generally a property is associated with a data member. But
this is not necessary. The get accessor can return a value
without accessing a data member. For example, we can write
a get property that returns system time without using a data
member. The data type of a property can be a preliminary data
type or a user-defined data type.
Indexers
An indexer is a new syntax that allows us to use an object
as if the object itself is an array. This syntax is used if
the class contains an array as a data member. An indexer allows
access to the array elements within the class using the [
] operator with an object. In one sense, we overload the [
] operator. Unlike arrays, indexers allow usage of non-integer
subscripts as well. Below, we see a program in which an indexer
takes a string as a subscript.
using System ;
namespace stringindexer
{
class sample
{
string[ ] english = new string[ ] {Sunday, Monday, Tuesday,
Wednesday, Thursday, Friday, Saturday} ;
string[ ] hindi = new string[ ] {Itwar, Somwar, Mangalwar,
Budhwar, Guruwar, Shukrawar, Shaniwar} ;
public string this [string c]
{
get
{
for ( int i = 0 ; i < english.Length ; i++ )
{
if ( String.Compare ( c, english [ i ],
true ) == 0 )
return hindi [ i ] ;
}
return Not Found;
}
set
{
for ( int i = 0 ; i < english.Length ; i++ )
{
if ( String.Compare ( c, english [ i ],
true ) == 0 )
{
hindi [ i ] = value ;
break ;
}
}
}
}
}
class Class1
{
static void Main ( string[ ] args )
{
sample s = new sample( ) ;
Console.WriteLine ( s[Monday] ) ;
s[Monday] = Som ;
Console.WriteLine ( s[Monday] ) ;
}
}
}
In this example, the user would provide a string representing
a weekday in English. The get accessor of the indexer would
return the corresponding name in Hindi, whereas, set accessor
would store the specified name in Hindi for the corresponding
weekday in English. For example, s[Monday] should
return Somwar. Similarly, s[Monday]
= Som should set Som as Monday's equivalent
Hindi name. To implement this, we have declared two arrays
of stringsenglish and hindi as data members of class
sample. In Main( ), we have instantiated an object of sample
and called the get accessor through the statement Console.WriteLine
( s [ Monday ] ) ;
Monday would get collected in c in the get accessor.
If the specified weekday is available in the english array
we have returned its Hindi equivalent from the hindi array.
We have done a case insensitive comparison by mentioning true
as a third parameter of the Compare( ) method.
Next, we have called the set accessor through the statement
s
[ Monday ] = Som ;
The string Monday would get collected in c. We
have stored the name Som, which is available in
the implicit parameter value, in the hindi array.
Indexers are nameless. It means that unlike properties we
cannot assign name to an indexer. We use the this reference
for writing indexers. Indexers may be overloaded. We can write
one indexer for a 1-D array and another for a 2-D array in
the same class. Needless to say, a 2-D indexer is accessed
using [ , ] syntax.
Although indexers allow us to use an object as an array, we
cannot use it in a foreach loop like an array. This is because
foreach works only with collections. Writing an indexer does
not qualify a class to be a collection.
It is not possible to write indexers for jagged arrays because
a statement such as public int this [ int index1] [ int index2
] results in an error.
Lastly, indexers cannot be declared as static because of the
simple reason that the this reference is not available in
static methods.
 |
Yashavant
Kanetkar, one of the first Express Computer columnists,
is an established software expert, speaker and author
with several best-sellers to his credit, including titles
like “Let Us C” and the “Fundas” series. Contact him at
kanet@nagpur.dot.net.in |
|