[C #] Use the indexer to treat class members (properties) like a list

3 minute read

I want to be able to access the property members of the data type class with an indexer like a list.

Subject

Make the properties of the UserInfo class below accessible by the indexer.

UserInfo.cs


public class UserInfo
{
 public UserInfo(List<String> userList)
 {
  ID=userList[0];
    Name=userList[1];
    Password=userList[2];
    email=userList[3];
  }
  public string ID{get;set;}
  public string Name{get;set;}
  public string Password{get;set;}
  public string email{get;set;}
}

Pre-preparation Access with subscript

userInfo.cs


public class UserInfo
{      
  public UserInfo(List<String> userList)
  {
    var properties = typeof(UserInfo).GetProperties();
    {
      for (var i = 0; i < userList.Count; i++)
      {
        var name = properties[i].Name;
        //Initialize properties collectively with userList
        this[name] = userList[i];
      }
    }          
  }
  public string ID{get;set;}
  public string Name{get;set;}
  public string Password{get;set;}
  public string email{get;set;}
 private string this[string propertyName]
  {
    get => typeof(UserInfo).GetProperty(propertyName).GetValue(this).ToString();
    set => typeof(UserInfo).GetProperty(propertyName).SetValue(this, value);
  }
}

Commentary

string this[string propertyName]
By adding this property, you can access by subscript.
get
typeof (class name) .GetProperty (propertyName) .GetValue (this)

↑ Since the return value of GetValue is object type, it is converted to string type.

set
typeof (class name) .GetProperty (propertyName) .SetValue (this, value)

constructor

  • typeof(UserInfo).GetProperties()
    Get class properties as an array.
  • properties[i].Name
    Since each property name can be acquired, loop processing becomes possible.

It doesn’t make much sense as it is, so make it accessible with an indexer.

Access with production 1 indexer

Add the following to the UserInfo class

userInfo.cs


private List<string> NameList;
public string this[int num]
{
  get => this[NameList[num]];
  set => this[NameList[num]] = value;
}

NameList is used as a list containing a list of property names (used for indexing property names).
string this[int num]
Wrap this [string propertyName].
Convert to the subscript of this [string propertyName] with NameList [num].

This will allow you to access it with an indexer.

However, this alone cannot be used as an enumeration type.

Production 2 Allows enumeration

Inherit IEnumerable and create IEnumerable interface.

By implementing GetEnumerator, it can be handled as an enumeration type.

userInfo.cs


//Change of UsefInfo, describe only additional parts
public class UserInfo : IEnumerable<string>
{
  //GetEnumerator implementation
 public IEnumerator<string> GetEnumerator()
 {
  for (var i = 0; i < NameList.Count; i++)
   {
    yield return this[i];
  }
 }
  //IEnumerable(Non-generic type)Also implements GetEnumerator
 System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
 {
   return this.GetEnumerator();
 }
}

Overall picture

UserInfo.cs


public class UserInfo : IEnumerable<string>
{      
  public UserInfo(List<String> userList)
  {
    var properties = typeof(UserInfo).GetProperties();
    NameList = new List<string>();
    //Extract each Name from properties
    foreach (var (name, index) in properties.Select((prop, index) => (prop.Name, index)))
    {
      if(index == properties.length - 1)
      {
        //The end of the array is this property, so skip it
        break;
      }
      //Create a list of UserInfo property names
      NameList.Add(name);
      //Initialize all properties
      this[name] = headerlist[index];
    }
  }
  public string ID{get;set;}
  public string Name{get;set;}
  public string Password{get;set;}
  public string email{get;set;}
  //Property index usage
  private List<string> NameList;
  
  //For access by subscript
 private string this[string propertyName]
  {
    get => typeof(UserInfo).GetProperty(propertyName).GetValue(this).ToString();
    set => typeof(UserInfo).GetProperty(propertyName).SetValue(this, value);
  }
  //For access with indexer
  public string this[int num]
  {
    get => this[NameList[num]];
    set => this[NameList[num]] = value;
  }
  //For assignment to list type
  public List<string> ToList()
  {
    var res = new List<string>();
    NameList.ForEach(name => res.Add(this[name]));
    return res;
  }
  public IEnumerator<string> GetEnumerator()
 {
  for (var i = 0; i < NameList.Count; i++)
  {
   yield return this[i];
  }
 }  
 System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
 {
   return this.GetEnumerator();
 }
}

result

var User=new UserInfo(new List<string>{"012","user","pass","[email protected]"});
//Access by subscript
User[0] = "dummy";
if(User.ID == "dummy")
{
	//match
}
Console.WriteLine(User[3]);
//[email protected]
    
foreach(var val in User)
{
  Console.WriteLine(val);
  //012
  //user
  //pass
  //[email protected]
}
var list=User.ToList()
//list:{"012","user","pass","[email protected]"}

You can now access with an indexer and loop with foreach.
I was able to do it, but I feel that there are many steps and it is redundant.
I would appreciate it if you could tell me if there is a better way.

reference

[C #] Access the property by property name