• Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 395
  • Last Modified:

retrieving Class object element by index

Hi,
if I have a class such as Test below and I create a new instance Test T = new Test();  How can I now reference object T by index. For instance if I want to place the value of T into a comma delimited string I could do the following

string Str = T.fld1+","+T.fld2+","+T.fld3+","+T.fld4


However I would like to be able to do something like this

for(int x=0;x<=4;x++)
{
Str=T[ x ]+","
}


Is there a way to do this ?

regards
Pat

    public class Test
    {
        public string fld1 { get; set; }
        public string fld2 { get; set; }
        public string fld3 { get; set; }
        public string fld4 { get; set; }
  public Test()
  {
fld1="test1";
fld2="test2";
fld3="test3";
fld4="test4";
  }  
}
0
pclarke7
Asked:
pclarke7
6 Solutions
 
käµfm³d 👽Commented:
You could implement the index operator on your class:

public class Test
{
    public string fld1 { get; set; }
    public string fld2 { get; set; }
    public string fld3 { get; set; }
    public string fld4 { get; set; }
    public Test()
    {
        fld1 = "test1";
        fld2 = "test2";
        fld3 = "test3";
        fld4 = "test4";
    }

    public string this[int index]
    {
        get
        {
            switch (index)
            {
                case 1:
                    return this.fld1;
                case 2:
                    return this.fld2;
                case 3:
                    return this.fld3;
                case 4:
                    return this.fld4;
                default:
                    throw new IndexOutOfRangeException("Invalid field index.");

            }
        }
    }

Open in new window


Just be careful, as this is a brittle design, and it leads to multiple places that have to be edited in the event of (applicable) changes.
0
 
it_saigeDeveloperCommented:
Perhaps something like:
using System;
using System.Linq;

namespace EE_Q28564134
{
	class Test
	{
		public string Field1 { get; set; }
		public string Field2 { get; set; }
		public string Field3 { get; set; }
		public string Field4 { get; set; }

		public Test()
		{
			Field1 = "test1";
			Field2 = "test2";
			Field3 = "test3";
			Field4 = "test4";
		}

		public string this[int i]
		{
			get { return (from field in typeof(Test).GetProperties() where field.Name.Equals(string.Format("Field{0}", i)) select (string)field.GetValue(this, null)).FirstOrDefault(); }
			set { (from field in typeof(Test).GetProperties() where field.Name.Equals(string.Format("Field{0}", i)) select field).FirstOrDefault().SetValue(this, value, null); }
		}
	}

	class Program
	{
		static void Main(string[] args)
		{
			Test tst = new Test();
			string str = string.Empty;
			for (int i = 0; i < 4; i++)
				str = string.Format("{0}{1}+,", str, tst[i + 1]);

			Console.WriteLine(str);
			Console.ReadLine();
		}
	}
}

Open in new window


Produces the following output:Capture.JPG
Echoing Kaufmed's warning.

-saige-
0
 
käµfm³d 👽Commented:
If you go with it_saige's solution--which is the same solution, but with added Reflection to make the code more dynamic--be sure to add appropriate error checking in. For instance, if you were to pass the value 5 to the index, his solution would return null. But does null mean that the value itself is null or that the property does not exist?
0
The new generation of project management tools

With monday.com’s project management tool, you can see what everyone on your team is working in a single glance. Its intuitive dashboards are customizable, so you can create systems that work for you.

 
it_saigeDeveloperCommented:
@kaufmed, mine is only posted after yours because you were quicker.  I was still working on mine.  I feel like the slow kid taking the test in class.  LOL

But kaufmed is correct.  Mine is essentially the same as his with the exception of being more dynamic but will return null (since a default string is a null value) in cases where the index is out of bounds (so to speak).

Example -
using System;
using System.Linq;

namespace EE_Q28564134
{
	class Test
	{
		public string Field1 { get; set; }
		public string Field2 { get; set; }
		public string Field3 { get; set; }
		public string Field4 { get; set; }

		public Test()
		{
			Field1 = "test1";
			Field2 = "test2";
			Field3 = "test3";
			Field4 = "test4";
		}

		public string this[int i]
		{
			get { return (from field in typeof(Test).GetProperties() where field.Name.Equals(string.Format("Field{0}", i)) select (string)field.GetValue(this, null)).FirstOrDefault(); }
			set { (from field in typeof(Test).GetProperties() where field.Name.Equals(string.Format("Field{0}", i)) select field).FirstOrDefault().SetValue(this, value, null); }
		}
	}

	class Program
	{
		static void Main(string[] args)
		{
			Test tst = new Test();
			string str = string.Empty;
			Console.WriteLine("This works");
			for (int i = 0; i < 4; i++)
				str = string.Format("{0}{1}+,", str, tst[i + 1]);
			Console.WriteLine(str);

			Console.WriteLine();
			str = string.Empty;

			Console.WriteLine("Added error checking and forced an error");
			for (int i = 0; i < 5; i++)
				str = string.Format("{0}{1}+,", str, !string.IsNullOrEmpty(tst[i + 1]) ? tst[i + 1] : string.Format("Field or value for Test{0}; does not exist", i + 1));
			Console.WriteLine(str);

			Console.WriteLine();
			str = string.Empty;

			Console.WriteLine("Now lets really get wild");
			tst[1] = "Changed1";
			tst[2] = "Changed2";
			tst[3] = "Changed3";
			// Forcing an error
			try { tst[5] = "Changed5"; }
			catch (Exception) { Console.WriteLine("Oops, you can't do that"); }
			Console.WriteLine();

			for (int i = 0; i < 5; i++)
				str = string.Format("{0}{1}+,", str, !string.IsNullOrEmpty(tst[i + 1]) ? tst[i + 1] : string.Format("Field or value for Test{0}; does not exist", i + 1));
			Console.WriteLine(str);
			Console.ReadLine();
		}
	}
}

Open in new window


Now produces the following output:Capture.JPG
-saige-
0
 
käµfm³d 👽Commented:
; )
0
 
Jacques Bourgeois (James Burger)PresidentCommented:
Personally, I would have designed the class so that these fields are an array. It would then be very easy to look through them. It would also enable you to easily add new fields later on without causing problems with existing applications.
0
 
Richard LeeSoftware EnthusiastCommented:
I would firstly reevaluate why you wish to take this approach. If you wish to access the properties by an index I would suggest using a collection based approach.

If you expand on your requirements then I believe a better approach could be provided. While the code samples above solve your problem, as highlighted these approached are prone to bugs creeping into your application. I would warn that spend some time to evaluate your requirements and come up with a better architectural approach as opposed to a quick hack.

public string[] Field { get; set; }

Open in new window


This code would be way more resilient in the long run. I offer credit to @Jacques Bourgeois as he suggested this before I even viewed the question. I simply elaborate and stress, since I have been down this path many times. There is no compromise for good architectural designs.
0
 
pclarke7Author Commented:
Thanks to all for your comments. Index operator is exactly what I was looking for and the various implementations of it were great to see. I don't think that there are any design issues here as the data that I am trying to access by index is not related in such a way that i should be placed into an array. I just happen to have a lot of data that can be accessed easier and cleaner by index. I am a big fan of  strongly typed data however there are times when accessing this data is best done by index.

regards
Pat
0

Featured Post

Never miss a deadline with monday.com

The revolutionary project management tool is here!   Plan visually with a single glance and make sure your projects get done.

Tackle projects and never again get stuck behind a technical roadblock.
Join Now