Indexers (I think!)

  • Thread starter Thread starter daz_oldham
  • Start date Start date
D

daz_oldham

Hi everyone

I am just trying to find how to implement Indexers... or at least that
is what I think I want to implement!

Very basically, in my database I have a table of T_Hotels which has
many entries in T_Rooms.

In my C#, I would like to be able to go:

// Get a new instance of the Hotel object for a given hotel ID
Hotel oHotel = new Hotel(iHotelID);

// Write down the name of all the rooms in the oHotelObject
for(Int32 i=0; i<oHotel.Rooms.Count; i++)
{
Response.Write(oHotel.Rooms.Name);
}

The actual making of the classes and setting the base type I am fine
with, it is just the creation of the array of children (rooms) that I
am struggling with.

Many thanks in advance

Darren
 
Hi Darren,

Yes, it's an indexer that you want, however you don't need to create your
own for your sample code to work. Here's an example that does both (2.0
framework code):

class Room
{
public string Name { get { return name; } }

private readonly string name;

public Room(string name)
{
this.name = name;
}
}

class Hotel
{
// indexers look like properties with "this" as their name
// and brackets instead of parenthesis
public Room this[int index]
{
get
{
return rooms[index];
}
}

public Room this[string name]
{
get
{
// in 1.* framework applications you can
// iterate the entire collection in a foreach

return rooms.Find(
// using an anonymous method
delegate(Room room)
{
return room.Name == name;
});
}
}

public Room[] Rooms
{
get
{
return rooms.ToArray();
}
}

public int RoomCount
{
get
{
return rooms.Count;
}
}

// in 1.* framework applications you can use ArrayList here:

private readonly List<Room> rooms = new List<Room>(
new Room[] {
new Room("1A"), new Room("2B"), new Room("3C") });
}


Here's some ways to use the Hotel class:

Hotel hotel = new Hotel();

Console.WriteLine(hotel.RoomCount); // 3
Console.WriteLine(hotel.Rooms[1].Name); // 2B
Console.WriteLine(hotel[1].Name); // 2B
Console.WriteLine(hotel["3C"].Name); // 3C
 
Thanks Dave - that reply makes what is quite a difficult subject for me
to get my head around very easy!

The next question I have is, what is the best way of populating the
List<Room> dynamically... i.e. from a DataSet?

Many thanks (understatement)

Darren

Dave said:
Hi Darren,

Yes, it's an indexer that you want, however you don't need to create your
own for your sample code to work. Here's an example that does both (2.0
framework code):

class Room
{
public string Name { get { return name; } }

private readonly string name;

public Room(string name)
{
this.name = name;
}
}

class Hotel
{
// indexers look like properties with "this" as their name
// and brackets instead of parenthesis
public Room this[int index]
{
get
{
return rooms[index];
}
}

public Room this[string name]
{
get
{
// in 1.* framework applications you can
// iterate the entire collection in a foreach

return rooms.Find(
// using an anonymous method
delegate(Room room)
{
return room.Name == name;
});
}
}

public Room[] Rooms
{
get
{
return rooms.ToArray();
}
}

public int RoomCount
{
get
{
return rooms.Count;
}
}

// in 1.* framework applications you can use ArrayList here:

private readonly List<Room> rooms = new List<Room>(
new Room[] {
new Room("1A"), new Room("2B"), new Room("3C") });
}


Here's some ways to use the Hotel class:

Hotel hotel = new Hotel();

Console.WriteLine(hotel.RoomCount); // 3
Console.WriteLine(hotel.Rooms[1].Name); // 2B
Console.WriteLine(hotel[1].Name); // 2B
Console.WriteLine(hotel["3C"].Name); // 3C

--
Dave Sexton

daz_oldham said:
Hi everyone

I am just trying to find how to implement Indexers... or at least that
is what I think I want to implement!

Very basically, in my database I have a table of T_Hotels which has
many entries in T_Rooms.

In my C#, I would like to be able to go:

// Get a new instance of the Hotel object for a given hotel ID
Hotel oHotel = new Hotel(iHotelID);

// Write down the name of all the rooms in the oHotelObject
for(Int32 i=0; i<oHotel.Rooms.Count; i++)
{
Response.Write(oHotel.Rooms.Name);
}

The actual making of the classes and setting the base type I am fine
with, it is just the creation of the array of children (rooms) that I
am struggling with.

Many thanks in advance

Darren
 
Hi Darren,
Thanks Dave - that reply makes what is quite a difficult subject for me
to get my head around very easy!

The next question I have is, what is the best way of populating the
List<Room> dynamically... i.e. from a DataSet?

I'm not sure there is a best way, but there are certainly many ways
depending on several factors. As a matter of fact, you could even use a
DataTable instead of List<Room> if you're going to be filling one anyway.
But here's an example of how to fill the list and classes from a DataSet
(you can place the code in the Main method of a console application):

// You're probably going to want to use a strong-Typed DataSet
// if you're not already, but for the sake of simplicity I won't here
DataSet data = new DataSet();

// assuming that you're using Sql Server:
SqlDataAdapter adapter = new SqlDataAdapter(
"SELECT * FROM T_Hotels", connString);

// create a new table in DataSet named Hotels
// and fill it with data from the database
adapter.Fill(data, "Hotels");

adapter.SelectCommand.CommandText =
"SELECT * FROM T_Rooms";

// create a new table in DataSet named Rooms
// and fill it with data from the database
adapter.Fill(data, "Rooms");

DataTable hotelsData = data.Tables["Hotels"];

// create primary key constraint on "ID" column
hotelsData.Constraints.Add("PK_Hotels",
hotelsData.Columns["ID"], true);

DataTable roomsData = data.Tables["Rooms"];

// create foreign key constraint
// (we'll use this to look up related records)
roomsData.ParentRelations.Add("FK_Hotels_Rooms",
hotelsData.Columns["ID"], // parent key column
roomsData.Columns["HotelID"], true); // reference column

List<Hotel> hotels = new List<Hotel>();

foreach (DataRow hotelRow in hotelsData.Rows)
{
List<Room> rooms = new List<Room>();

foreach (DataRow roomRow in hotelRow.GetChildRows(
"FK_Hotels_Rooms"))
{
rooms.Add(new Room((string) roomRow["Name"]));
}

hotels.Add(new Hotel(rooms));
}

Console.WriteLine("Hotel Count: " + hotels.Count);

foreach (Hotel hotel in hotels)
{
Console.WriteLine("Hotel Room Count: " + hotel.RoomCount);

foreach (Room room in hotel.Rooms)
{
Console.WriteLine("\tRoom: " + room.Name);
}
}

You'll need to add a public constructor to my Hotels class for the code
above to compile:

public Hotel(List<Room> rooms)
{
if (rooms == null)
throw new ArgumentNullException("rooms");

this.rooms = rooms;
}
Many thanks (understatement)

NP :)
 
Back
Top