question on a simple indexer (c#) - c#

in the following indexer code block, why do we need:
public string this[int pos]
{
get
{
return myData[pos];
}
set
{
myData[pos] = value;
}
}
what exactly does "this" in this[int pos] do? Thanks
/// Indexer Code Block starts here
using System;
/// <summary>
/// A simple indexer example.
/// </summary>
class IntIndexer
{
private string[] myData;
public IntIndexer(int size)
{
myData = new string[size];
for (int i = 0; i < size; i++)
{
myData[i] = "empty";
}
}
public string this[int pos]
{
get
{
return myData[pos];
}
set
{
myData[pos] = value;
}
}
static void Main(string[] args)
{
int size = 10;
IntIndexer myInd = new IntIndexer(size);
myInd[9] = "Some Value";
myInd[3] = "Another Value";
myInd[5] = "Any Value";
Console.WriteLine("\nIndexer Output\n");
for (int i = 0; i < size; i++)
{
Console.WriteLine("myInd[{0}]: {1}", i, myInd[i]);
}
}
}

It means that you can use the indexer on the object itself (like an array).
class Foo
{
public string this[int i]
{
get { return someData[i]; }
set { someData i = value; }
}
}
// ... later in code
Foo f = new Foo( );
string s = f[0];

From a c# syntax perspective:
You need this because - how else would you declare it? Functionality on a class must have a name, or address, by which to reference it.
A method signature is:
[modifiers] [type] [name] (parameters)
public string GetString (Type myparam);
A property signature is:
[modifiers] [type] [name]
public string MyString
A field signature is:
[modifiers] [type] [name]
public string MyString
Since an indexer has no name, it would not make much sense to write:
public string [int pos]
So we use this to denote it's "name".

This is just marker for compiler to know that that property has indexer syntax.
In this case it enables myInd to use "array syntax" (e.g. myInd[9]).

The 'this' keyword indicates that you are defining behavior that will be invoked when your class is accessed as if it was an array. Since your defining behavior for the class instance, use of the 'this' keyword in that context makes sense. You don't call myInd.indexer[], you call myInd[].

It allows your class to behave in a similar manner to an array. In this case, your indexer is allowing you to reference myData transparently from outside the IntIndexer class.
If you didn't have the indexer declared, the following code would fail:
myInd[1] = "Something";

The "this" in your case specifies that this property is the indexer for this class. This is the syntax in C# to define an indexer on a class, so you can use it like:
myInd[9] = ...

Related

diplaying data in private array by using indexers in c#

I am declaring two private arrays in indexes and displaying the data in main. However, it is not displaying any one tell me how to display the data in the two private arrays in indexers?
class Program
{
static void Main(string[] args)
{
student sc = new student();
for (int i = 0; i < sc.mlength; i++)
{
Console.WriteLine(sc[i]);
}
Console.ReadLine();
//i am declaring two private arrays in indexes and displaying the data in main is not displaying any one tell me how to display the data in the two private arrays in indexers?
}
}
public class student
{
private int[] _marks = new int[] { 60, 68, 70 };
private string[] _names = new string[] { "suri", "kumar", "suresh" };
public int this[int i]
{
get
{
return _marks[i];
}
set
{
_marks[i] = value;
}
}
public string this[int i]
{
get
{
return _names[Convert.ToInt32(i)];
}
set
{
_names[Convert.ToInt32(i)] = value;
}
}
public int mlength
{
get
{
return _marks.Length;
}
}
public int nlenght
{
get
{
return _names.Length;
}
}
}
}
Indexers allow your class to be used just like an array. On the inside of a class, you manage a collection of values any way you want. These objects could be a finite set of class members, another array, or some complex data structure. Regardless of the internal implementation of the class, its data can be obtained consistently through the use of indexers. Here’s an example.
Example:
using System;
class IntIndexer
{
private string[] myData;
public IntIndexer(int size)
{
myData = new string[size];
for (int i=0; i < size; i++)
{
myData[i] = "empty";
}
}
public string this[int pos]
{
get
{
return myData[pos];
}
set
{
myData[pos] = value;
}
}
static void Main(string[] args)
{
int size = 10;
IntIndexer myInd = new IntIndexer(size);
myInd[9] = "Some Value";
myInd[3] = "Another Value";
myInd[5] = "Any Value";
Console.WriteLine("\nIndexer Output\n");
for (int i=0; i < size; i++)
{
Console.WriteLine("myInd[{0}]: {1}", i, myInd[i]);
}
}
}
The IntIndexer class has a string array named myData. This is a private array that external users can’t see. This array is initialized in the constructor, which accepts an int size parameter, instantiates the myData array, and then fills each element with the word “empty”.
The IntIndexer class has a string array named myData. This is a private array that external users can’t see. This array is initialized in the constructor, which accepts an int size parameter, instantiates the myData array, and then fills each element with the word “empty”.
The next class member is the Indexer, which is identified by the this keyword and square brackets, this[int pos]. It accepts a single position parameter, pos. As you may have already guessed, the implementation of an Indexer is the same as a Property. It has get and setaccessors that are used exactly like those in a Property. This indexer returns a string, as indicated by the string return value in the Indexer declaration.
The Main() method simply instantiates a new IntIndexer object, adds some values, and prints the results. Here’s the output:
Indexer Output
myInd[0]: empty
myInd[1]: empty
myInd[2]: empty
myInd[3]: Another Value
myInd[4]: empty
myInd[5]: Any Value
myInd[6]: empty
myInd[7]: empty
myInd[8]: empty
myInd[9]: Some Value

How to access the indexer with Interface Explicitly implemended

When we explicitly implement an interface for an indexer, how can we able to set and get value form the indexer after creating object. or inside the same class constructor
namespace oopsTesting.Indexer
{
public interface IndexerInterface
{
char this[int index] { get; set;}
}
class Indexer : IndexerInterface
{
string name = "Babu Kumarasamy";
StringBuilder sbName = new StringBuilder("Babu Kumarasamy");
public Indexer()
{
for (int i = 0; i < sbName.Length; i++)
{
//How to access the indexer here
Console.WriteLine("Property Indexer: {0}, StringBuilder: {1}", this[i], sbName[i]);
}
}
char IndexerInterface.this[int index]
{
get { return name[index]; }
set
{
//Property or indexer 'string.this[int]' cannot be assigned to -- it is read only
//Strings are immutable which is why there's no setter, you can however use a string builder:
//name[index] = value;
sbName[index] = value;
}
}
}
class Program
{
static void Main(string[] args)
{
GenericIndexerTest objGenIndexer = new GenericIndexerTest();
//How to access the indexer here
}
}
}
You can create a new instance of Indexer, assigning it to a variable of type IndexerInterface:
IndexerInterface ii = new Indexer();
char c = ii[0];
(Note: This answer assumes GenericIndexerTest inherits Indexer in your code)
The same way as you access any explicitly implemented interface, by casting to the interface type:
GenericIndexerTest objGenIndexer = new GenericIndexerTest();
((IndexerInterface)objGenIndexer)[0] = 'A';
or code to the interface, not the implementation:
IndexerInterface objGenIndexer = new GenericIndexerTest();
objGenIndexer[0] ='A';

Get access to my derived class members

I have several classes that inhabit from this class:
public abstract class Class1
{
private string _protocol;
private static List<Plus> _class1Objects;
public string Protocol
{
get { return _protocol; }
set { _protocol = value; }
}
public static List<Plus> Class1Objects
{
get { return _class1Objects; }
set { _class1Objects = value; }
}
}
And the derive class:
public class Class2 : Plus
{
public bool name;
public int id;
}
public Webmail(string name, int id)
{
if (Class1Objects == null)
Class1Objects = new List<class1>();
.....
Class1Objects.Add(this);
}
And after my list is full of Class1Objects:
for (int i = 0; i < Class1.Class1Objects.Count; i++)
{
if (Class1.Class1Objects[i].GetType() == typeof(Class2))
}
(Class2)Class1.Class1Objects[i].
}
}
Here after (Class2)Class1.Class1Objects[i]. i cannot see my Class2 memners
You need one additional paranthese:
((Class2)Class1.Class1Objects[i]).
At the moment it is read as the following:
(Class2)(Class1.Class1Objects[i].) //<= at the '.' it is still a class1
BUT as David said in his comment: If all are of type Class2 it should be a collection of that type and if not you should check the type, altogether with foreach:
foreach(var item in Class1.Class1Objects)
{
if(item is Class2)
((Class2)Class1.Class1Objects[i]).
}
It would be cleaner to use as:
for (int i = 0; i < Class1.Class1Objects.Count; i++)
{
var c2 = Class1.Class1Objects[i] as Class2;
if (c2!=null)
}
c2.<whatever was meant to come after the .>
}
}
You might also want to consider switching to foreach unless there's a specific reason you want to manually extract each element from the List, e.g. if you're actually storing new values back into the list.
The correct syntax would be:
((Class2)Class1.Class1Objects[i]).name;
Because in your case, when you type something like this:
(Class2)Class1.Class1Objects[i].name;
You try to access the member name of Class1.Class1Objects[i], and only after that you try to cast it to Class2.
Also, the whole loop would be much simpler if you used foreach:
using System.Linq;
foreach(Class2 c in Class1.Class1Objects.OfType<Class2>())
{
Console.WriteLine(c.name); // or whatever you need to do with it
}

Returning results from array that contains two types of results

Hello I'm trying to retrun array type named ZverejnenyUcetType but the issue is that this array might contain two types : StandartniUcetType and NestandardniUcetType.
So the issue is when I try to return the array like this:
string[] dic_vstup = new string[] { (line) };
RozhraniWSDL.InformaceOPlatciType[] dic_vystup;
RozhraniWSDL.rozhraniCRPDPH srv = new RozhraniWSDL.rozhraniCRPDPH();
StatusType status = srv.getStatusNespolehlivyPlatce(dic_vstup, out dic_vystup);
string abc = status.bezVypisuUctu.ToString(); // If it is already a string, then ToString not needed
for (int i = 0; i < dic_vystup.Length; i++)
{
RozhraniWSDL.InformaceOPlatciType info = dic_vystup[i];
for (int x = 0; x <= 3; x++)
{
file2.WriteLine((((RozhraniWSDL.StandardniUcetType)(info.zverejneneUcty[x].Item)).cislo) + "-"
+ (((RozhraniWSDL.StandardniUcetType)(info.zverejneneUcty[x].Item)).cislo) + "/"
+ (((RozhraniWSDL.StandardniUcetType)(info.zverejneneUcty[x].Item)).kodBanky));
}}
I get following exception: unable to cast object of type RozhraniWSDL.NestandardniUcetType to type RozhraniWSDL.StandardniUcetType.
NestandardniUcetType contains only one item - cislo
StandartníUcetType have 3 items- predcislo, cislo, kod banky
Here is an image of the array:
I thought that the solution might be to determinate which of the result are of type StandartniUcetType and which are NestandardniUcetType.
I would like to ask if this is possible to do?
I found this solution more common.
Thank you for your time.
If the array has two different types, you could add an if statement, like this:
if (info.zverejneneUcty[x].Item is RozhraniWSDL.StandardniUcetType) {
...
} else {
...
}
A slightly better approach would be to cast using the as operator, like this:
RozhraniWSDL.StandardniUcetType std = info.zverejneneUcty[x].Item as RozhraniWSDL.StandardniUcetType;
if (std != null) {
...
}
RozhraniWSDL.NestandardniUcetType nstd = info.zverejneneUcty[x].Item as RozhraniWSDL.NestandardniUcetType;
if (nstd != null) {
...
}
Finally, a very good approach would be writing two separate methods for the two types, and using dynamic to perform a dispatch. To do that, define two functions, like this:
static void WriteToFile(RozhraniWSDL.StandardniUcetType std, StreamWriter file) {
...
}
static void WriteToFile(RozhraniWSDL.NestandardniUcetType nstd, StreamWriter file) {
...
}
Now change your loop as follows:
for (int x = 0; x <= 3; x++) {
dynamic item = info.zverejneneUcty[x].Item;
WriteToFile(item, file2); // <<== Magic
}
Using the OfType extension method over the array will filter for the type you need
foreach (var item in info.zverejneneUcty.OfType<RozhraniWSDL.StandardniUcetType>())
{
file2.WriteLine(item.predcislo + "-" + item.cislo + "-" + item.kodBanky);
}
I'd redesign the types and remove the issue instead, through an abstract class, like this:
// I'm making up the inner types, adapt this to your code
public abstract class UcetType
{
public virtual object predcislo { get; set; }
public virtual object cislo { get; set; }
public virtual object kodBanky { get; set; }
public virtual void WriteToFile(StreamWriter file)
{
// build the string and write it to the file
// considering all properties
// this acts as "default" for this type and all derived ones
}
}
public class StandardniUcetType : UcetType
{
// This will use the abstract as-is
// with all 3 properties and the "default" WriteToFile() method
}
public class NestandardniUcetType : UcetType
{
/// <summary>
/// Attempting to use this will throw an exception
/// </summary>
public override object predcislo
{
get { throw new NotSupportedException(); }
set { throw new NotSupportedException(); }
}
/// <summary>
/// Attempting to use this will throw an exception
/// </summary>
public override object kodBanky
{
get { throw new NotSupportedException(); }
set { throw new NotSupportedException(); }
}
// change the way WriteToFile behaves
public override void WriteToFile(StreamWriter file)
{
// build the string and write it to the file
// only considering 'cislo' property
}
}
// Usage example, based on question
for (int i = 0; i < dic_vystup.Length; i++)
{
RozhraniWSDL.InformaceOPlatciType info = dic_vystup[i];
// I assume "3" is the expected length of the array ? Change the for like this:
for (int x = 0; x <= info.zverejneneUcty.Length; x++)
{
//Delegate to the WriteToFile() method the task to build and write the line!
info.zverejneneUcty[x].Item.WriteToFile(file2);
}
}
I see no benefit in a dynamic approach here. This is more readable and easy to expand in the future (need a new type ? just derive UcetType in a new class and override away).

Help in Indexers code

I'm currently studying indexers chapter, but I'm unable to understand "this[int pos]" and "this[string data]" of the following code. Could anyone help me in this?
class OvrIndexer
{
private string[] myData;
private int arrSize;
public OvrIndexer(int size)
{
arrSize = size;
myData = new string[size];
for (int i=0; i < size; i++)
{
myData[i] = "empty";
}
}
public string this[int pos]
{
get
{
return myData[pos];
}
set
{
myData[pos] = value;
}
}
public string this[string data]
{
get
{
int count = 0;
for (int i=0; i < arrSize; i++)
{
if (myData[i] == data)
{
count++;
}
}
return count.ToString();
}
set
{
for (int i=0; i < arrSize; i++)
{
if (myData[i] == data)
{
myData[i] = value;
}
}
}
}
One accesses the index by integer, and the other by string:
var indexer = new OvrIndexer();
// Sets the first item of the indexer to "Value1"
indexer[0] = "Value1";
// Sets the item identified by key "Key2" to value "Value2"
indexer["Key2"] = "Value2";
This is just the defining of indexers for your class, so you can use syntax like this to get the contents of the class internal array.
myOvrIndexer[3]
will return the 4th element of the myData array.
myOvrIndexer["Test"]
will return the first element with the content Test.
Note that this class is mostly useless as it just wraps a array and do not add any useful functionality except the indexer receiving a string instead of index, but from a learning perspective this class should do a good job explaining whats going on.
The main purpose of the indexers is to avoid having to create methods, and thereby having to write syntax like this:
myOvrIndexer.GetElement(3);
myOvrIndexer.SetElement(3, myValue);
I think we both agree that this syntax looks better:
myOvrIndexer[3];
myOvrIndexer[3] = myValue;
this[int pos]
The getter will return the value at index specified.
The setter will set the value at the index specified.
whereas
this[string data]
The getter will return the count of occurances of the value you are looking up.
The setter will replace all value matches found with the new value.

Categories

Resources