Home > Software engineering >  Get property value of object via index
Get property value of object via index

Time:12-09

Issue:

I have an object with properties that models the hours of the day. I would like to know if it's possible to index the properties of this object similar to how they are indexed in an array or dictionary and then get these values by their index.

Example:

internal class HoursOfDay
{
    [JsonProperty("hour00", NullValueHandling = NullValueHandling.Ignore)]
    public HourDetailsExample Hour00 { get; set; }

    [JsonProperty("hour01", NullValueHandling = NullValueHandling.Ignore)]
    public HourDetailsExample Hour01 { get; set; }

    [JsonProperty("hour02", NullValueHandling = NullValueHandling.Ignore)]
    public HourDetailsExample Hour02 { get; set; }

    [JsonProperty("hour03", NullValueHandling = NullValueHandling.Ignore)]
    public HourDetailsExample Hour03 { get; set; }

    [JsonProperty("hour04", NullValueHandling = NullValueHandling.Ignore)]
    public HourDetailsExample Hour04 { get; set; }

    [JsonProperty("hour05", NullValueHandling = NullValueHandling.Ignore)]
    public HourDetailsExample Hour05 { get; set; }

    [JsonProperty("hour06", NullValueHandling = NullValueHandling.Ignore)]
    public HourDetailsExample Hour06 { get; set; }

    [JsonProperty("hour07", NullValueHandling = NullValueHandling.Ignore)]
    public HourDetailsExample Hour07 { get; set; }

    [JsonProperty("hour08", NullValueHandling = NullValueHandling.Ignore)]
    public HourDetailsExample Hour08 { get; set; }

...

I would like to be able to access the properties of this object like this if possible:

var hoursOfDay = new HoursOfDay(); 
var h1 = hoursOfDay["0"] // or hoursOfDay[0] or hoursOfDay["hour00"]

I understand I could just turn this object into an array or a dictionary but I was just curious if indexing on the properties of an object is possible.

Edit I also understand this is something I can do with reflection. I want to know if I can do with indexing.

Edit2 Similarly, I also would like to know how to update the setter: example: var h1[0] = new HourDetailsExample("exampleData");

** Edit3** I've learned this can be added by adjusting the below answers to include a set {}

CodePudding user response:

You can create an indexer in your class

public HourDetailsExample this[int index] => index switch {
    0 => Hour00,
    1 => Hour01,
    2 => Hour02,
    3 => Hour03,
    4 => Hour04,
    5 => Hour05,
    6 => Hour06,
    7 => Hour07,
    8 => Hour08,
    _ => throw new IndexOutOfRangeException()
};

and you can overload it with a string index variant:

public HourDetailsExample this[string index] => index.ToLowerInvariant() switch {
    "0" or "hour00" => Hour00,
    "1" or "hour01" => Hour01,
    "2" or "hour02" => Hour02,
    "3" or "hour03" => Hour03,
    "4" or "hour04" => Hour04,
    "5" or "hour05" => Hour05,
    "6" or "hour06" => Hour06,
    "7" or "hour07" => Hour07,
    "8" or "hour08" => Hour08,
    _ => throw new IndexOutOfRangeException()
};

Now, all these variants are possible:

var hoursOfDay = new HoursOfDay();
var h1 = hoursOfDay[0];
var h2 = hoursOfDay["1"];
var h3 = hoursOfDay["Hour02"];
var h4 = hoursOfDay["hour03"];

The indexer can also have a setter, if you need to assign values by indexing:

public HourDetailsExample this[int index]
{
    get => index switch {
        0 => Hour00,
        ...
        _ => throw new IndexOutOfRangeException()
    };
    set {
        switch (index) {
            case 0: Hour00 = value; break;
            case 1: Hour01 = value; break;
            case 2: Hour02 = value; break;
            case 3: Hour03 = value; break;
            case 4: Hour04 = value; break;
            case 5: Hour05 = value; break;
            case 6: Hour06 = value; break;
            case 7: Hour07 = value; break;
            case 8: Hour08 = value; break;
            default: throw new IndexOutOfRangeException();
        }
    }
}

CodePudding user response:

You can always create indexer for the type:

internal class HoursOfDay
{
   // ...
    
    public HourDetailsExample this[int index]
    {
        get => index switch
        {
            0 => Hour00,
            1 => Hour01,
            // ...
            _ => throw new ArgumentOutOfRangeException(nameof(index), index, null) // or return null
        };
    }
}

If you don't want to write everything by hand - you can use some reflection but there would be some performance hit (though it can be mostly negated by "caching" it - see this answer for some inspiration).

  • Related