user10501500
user10501500

Reputation:

How do I loop through all fields in an object in C#?

I have an object like this:

public class Filters {
    public int var1 = 1, 
          var2 = 2, 
          var3 = 3;
}

I declare this object here:

Filters filter1 = new Filters();

And I want to access var1, var2, and var3 in a loop and do something with it. i.e.:

foreach (var prop in filter1.props) {
    Console.WriteLine(filter1[prop] + 3);
}

and the output would be:

4
5
6

I imagine I need to do a foreach loop for each property using foreach(PropertyInfo p in filter1.GetType().GetProperties()), but I don't know how to 1) loop through props var1, var2, var3, and 2) how to subset the prop from filter1 using the name stored in the variable

Upvotes: 3

Views: 15660

Answers (3)

arslanaybars
arslanaybars

Reputation: 1853

If you describe your variable as properties like bellow,

public class Filters
{
    public int var1 { get; set; } = 1;
    public int var2 { get; set; } = 2;
    public int var3 { get; set; } = 3;
}

You can access these properties with

GetType().GetProperties()

then the main method will give you what you ask for

static void Main(string[] args)
{
    Filters filter1 = new Filters();

    foreach (var prop in filter1.GetType().GetProperties())
    {
        Console.WriteLine("{0}={1}", prop.Name, (int)prop.GetValue(filter1, null) + filter1.GetType().GetProperties().Length);
    }
        
    Console.ReadKey();
}

Result will be

var1=4
var2=5
var3=6

Upvotes: 5

user10501500
user10501500

Reputation:

Thanks to everyone who answered-- a couple hints helped me get there. I just started in C# so I didn't know what fields/props were, so thanks @SeM @John. But with that, and with answers by @Icepickle & @arslanaybars with GetProperties() but for fields instead:

        FieldInfo[] fields = typeof(GeneralFilters).GetFields();
        for (int i = 0; i < fields.Length; i++)
        {
            //MANIPULATE HERE
            BlankTemplate tempFilter = (BlankTemplate)fields[i].GetValue(filters);
            // Ignore this for now.       tempFilter.selectedItems;
        }

where BlankTemplate is defined here:

public class BlankTemplate
{
    public string[] selectedItems;
    public bool selectAll = false;
}

And now in tempFilter I have the object that I need to use at every iteration

Thanks!!!

Edit: I realize that this doesn't answer the question of how to subset using the stringified name of the object fields. What I envisioned before is generating array of field names, then looping through and subsetting the data in the fields using the field names, like in javascript:

var fieldNames = Object.keys(filterObject);
for (var i = 0; i < fieldNames.length; i++) {
    doSomething( filterObject[fieldNames[i]] );
}

But it seems to be a bit different in C#

Upvotes: 1

Icepickle
Icepickle

Reputation: 12796

An alternative answer to your question could be the following, say you have a class of filters like the following

public class Filter 
{
    public IDictionary<string, object> Properties { get; } = new Dictionary<string, object>();
}

This would allow you to have a dynamic set of filters, you can assign new properties as a consumer and iterate the existing ones. That seems to fit your current requirements.

As for a real answer, as many in the comments have pointed out, if you want to iterate properties, then you should actually use them. In your sample code, you have provided fields instead.

So your class Filter would probably end up looking like this (note that I think var1...var3 are the most horrible names you can use as I cannot imagine what they might define in the end):

public class Filter 
{
    public int Var1 { get; set; } = 1;
    public int Var2 { get; set; } = 2;
    public int Var3 { get; set; } = 3;
}

and then you could have something similar like:

var filter = new Filter();
var filterType = filter.GetType();
var readableProperties = filterType.GetProperties().Where( p => p.GetGetMethod() != null );

foreach (var property in readableProperties) 
{
    var value = (int)property.GetValue( filter );
    Console.WriteLine( $"{property.Name} =  {value + 3}" );
}

To ensure that you only select those you actually want, you can ofcourse check the name if it equals to Var1, Var2, Var3 or matches a regex expression, or whatever you like to think of ;)

A sample of the code here, you can find in this dotnetfiddle (though without autoproperties and $)

Upvotes: 0

Related Questions