Share via

Struct For Each

AS 211 Reputation points
2021-02-22T14:26:39.217+00:00

All,

My, abbreviated, class definition are as follows:

public class Location
{   
      public struct StaffRequirment
      {
        public Guid DBRef;
        public DateTime StartTime;
        public DateTime EndTime;
        public Guid Skill;
      }

    public List<StaffRequirment> StaffRequirments = new List<StaffRequirment>();
}

  public static class Global
  {
        public static List<Location> Locations = new List<Location>();
  }

I'm trying to loop through the structure as follows:

        foreach (Location IndvLoc in Global.Locations)
        {
          foreach (IndvStaffReq in IndvLoc.StaffRequirments)


        }

I need to specify a type for IndvStaffReq. Is it possible to do this with a Struct, and if so how, or do I need to turn the Struct into a class?

Thanks

Developer technologies | C#
Developer technologies | C#

An object-oriented and type-safe programming language that has its roots in the C family of languages and includes support for component-oriented programming.

0 comments No comments

Answer accepted by question author

AS 211 Reputation points
2021-02-22T16:56:49.827+00:00

I found the solution:

 foreach (Location.StaffRequirment IndvStaffReq in IndvLoc.StaffRequirments)
          {

          }

I thought I tried that before posting but obviously not.

I will mark this as the answer as it's a direct answer to my question however cooldadtx provides some good information as well.

Was this answer helpful?

0 comments No comments

1 additional answer

Sort by: Most helpful
  1. Michael Taylor 61,221 Reputation points
    2021-02-22T14:37:34.767+00:00

    I need to specify a type for IndvStaffReq

    Since IndvLoc.StaffRequirements is a List<StaffRequirement> then the type of IndvStaffReq is StaffRequirement.

    foreach (StaffRequirement IndvStaffReq in IndvLoc.StaffRequirements)
    

    However it is generally just easier to use var and let the compiler figure this out. If you go this route then you can mouse over the variable in the IDE and see the type as well.

    //Note that local variables should generally be camel cased to avoid conflicts with Pascal cased members
    foreach (var IndvStaffReq in IndvLoc.StaffRequirements)
    

    Any type works with foreach provided it either implements IEnumerable, IEnumerable<T> or provides the required methods of that interface. Whether the stored type is a value type (struct) or class is irrelevant.

    But do note that value types (structs) use copy semantics for assignment and therefore you may be limited to what you do inside that foreach statement.

    //This will copy the current struct into IndvStaffReq, for the life of this iteration you have 2 copies in memory
    foreach (var IndvStaffReq in IndvLoc.StaffRequirements)
    {
       Console.WriteLine(IndvStaffReq.DBRef);   //OK, reading doesn't matter that you have 2 copies
       IndvStaffReq.EndTime = IndvStaffReq.StartTime.AddDays(1);  //Compiles (probably), but wrong
    };
    

    Because value types use copy semantics the foreach copies the entire struct into your temp local variable. Any changes you try to make will alter the copied value, not the one in the list. The only way to modify the properties of a struct inside the list is to replace the existing instance actually stored in the list. You cannot do that with a foreach, or at least easily since you need the index

    for (var index = 0; index < IndvLoc.StaffRequirements.Count; ++index)
    {
        //Get a value and make a change, but preference is for immutable structs
        var current = IndvLoc.StaffRequirements[index];
        current.EndTime = current.StartTime.AddDays(1);
    
        //Replace the current value with an updated one
        IndvLoc.StaffRequirements[index] = current;
    
    }
    

    This is how all value types work. In general value types (structs) should be immutable to ensure these kinds of changes are errors at compilation. Personally, in your scenario, I think a class makes more sense as the data isn't an atomic set of values (like a latlong or datetime) and therefore don't belong in a struct.

    Was this answer helpful?

    1 person found this answer helpful.

Your answer

Answers can be marked as 'Accepted' by the question author and 'Recommended' by moderators, which helps users know the answer solved the author's problem.