Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    text
    copied!<p>I personally like LukeH's answer quite a bit. The only issue is having to define the static StudentProperty class with static readonly delegate wrapper objects rather than your original eStudentProperty enum. Depending on your situation, this might not be easily usable by the caller.</p> <p>The advantage of that code is that each <code>StudentProperty&lt;T&gt;</code> object is strongly typed according to its associated property, allowing the EnumerateBy method to return a strongly typed <code>IEnumerable&lt;T&gt;</code>.</p> <p>Below is what I came up with. It's very similar to LukeH's answer in that I've provided a <code>PropertyValues</code> method similar to LukeH's <code>EnumerateBy</code> method, although my method returns an <code>IEnumerable</code> (non-generic). An issue with my implementation is that if you are iterating over a value-type property (such as Age), then there will be some boxing going on within the enumerator. However, if the consumer doesn't know enough about the property being iterated to call the <code>Ages</code> method that I've provided rather than <code>PropertyValues(eStudentProperty.Age)</code>, then boxing will most likely occur in the caller's code regardless of whether I'm able to return an <code>IEnumerable&lt;int&gt;</code> or an <code>IEnumerable</code>. So I would argue that anyone who needs to call the <code>PropertyValues</code> method because they cannot call the <code>Names</code>, <code>Cities</code>, or <code>Ages</code> methods will not be able to avoid boxing with any implementation.</p> <pre><code>class Program { static void Main(string[] args) { Students students = new Students(); students.AddStudent(new Student { Age = 20, Name = "Stud1", City = "City1" }); students.AddStudent(new Student { Age = 46, Name = "Stud2", City = "City2" }); students.AddStudent(new Student { Age = 32, Name = "Stud3", City = "City3" }); students.AddStudent(new Student { Age = 34, Name = "Stud4", City = "city4" }); // in these two examples, you know exactly which property you want to iterate, // so call the corresponding iterator method directly. foreach (string studentCity in students.Cities()) { Console.WriteLine(studentCity); } foreach (string studentName in students.Names()) { Console.WriteLine(studentName); } // in these three cases, the DoSomethingWithPropertyValues method will not know which property is being iterated, // so it will have to use the PropertyValues method DoSomethingWithPropertyValues(students, eStudentProperty.Age); DoSomethingWithPropertyValues(students, eStudentProperty.Name); DoSomethingWithPropertyValues(students, eStudentProperty.City); } static void DoSomethingWithPropertyValues(Students students, eStudentProperty propertyToIterate) { // This method demonstrates use of the Students.PropertyValues method. // The property being iterated is determined by the propertyToIterate parameter, // therefore, this method cannot know which specific iterator method to call. // It will use the PropertyValues method instead. Console.WriteLine("Outputting values for the {0} property.", propertyToIterate); int index = 0; foreach (object value in students.PropertyValues(propertyToIterate)) { Console.WriteLine("{0}: {1}", index++, value); } } } public class Students { private List&lt;Student&gt; m_Students = new List&lt;Student&gt;(); public void AddStudent(Student i_Student) { m_Students.Add(i_Student); } public IEnumerable PropertyValues(eStudentProperty property) { switch (property) { case eStudentProperty.Name: return this.Names(); case eStudentProperty.City: return this.Cities(); case eStudentProperty.Age: return this.Ages(); default: throw new ArgumentOutOfRangeException("property"); } } public IEnumerable&lt;string&gt; Names() { return m_Students.Select(s =&gt; s.Name); } public IEnumerable&lt;string&gt; Cities() { return m_Students.Select(s =&gt; s.City); } public IEnumerable&lt;int&gt; Ages() { return m_Students.Select(s =&gt; s.Age); } } public enum eStudentProperty { Name, Age, City } public class Student { public string Name { get; set; } public string City { get; set; } public int Age { get; set; } } </code></pre>
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload