Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Pass property itself to function as parameter in C#

You can pass a property accessor to the method.

List<Class1> SortBy(List<Class1> toSort, Func<Class1, IComparable> getProp)
{
    if (toSort != null && toSort.Count > 0) {
        return toSort
            .OrderBy(x => getProp(x))
            .ToList();
    }
    return null;
}

You would call it like this:

var result = SortBy(toSort, x => x.maxSpeed);

But you could go one step further and write your own extension method.

public static class CollectionExtensions
{
    public static List<TSource> OrderByAsListOrNull<TSource, TKey>(
        this ICollection<TSource> collection, Func<TSource,TKey> keySelector)

        if (collection != null && collection.Count > 0) {
            return collection
                .OrderBy(x => keySelector(x))
                .ToList();
        }
        return null;
    }
}

Now you can sort like this

List<Class1> sorted = toSort.OrderByAsListOrNull(x => x.maxSpeed);

but also

Person[] people = ...;
List<Person> sortedPeople = people.OrderByAsListOrNull(p => p.LastName);

Note that I declared the first parameter as ICollection<T> because it must fulfill two conditions:

  1. It must have a Count property
  2. It must be an IEnumerable<T> in order to be able to apply the LINQ method OrderBy.

List<Class1> is an ICollection<T> but also an array Person[] as many other collections.


So far, I have shown how you can read a property. If the method needs to set a property, you need to pass it a setter delegate as well

void ReadAndWriteProperty(Func<Class1, T> getProp, Action<Class1, T> setProp)

Where T is the type of the property.


You can use an lambda expression to pass property information:

void DoSomething<T>(Expression<Func<T>> property)
{
    var propertyInfo = ((MemberExpression)property.Body).Member as PropertyInfo;
    if (propertyInfo == null)
    {
        throw new ArgumentException("The lambda expression 'property' should point to a valid Property");
    }
}

Usage:

DoSomething(() => this.MyProperty);

What I found missing from @MatthiasG's answer is how to get property value not just its name.

public static string Meth<T>(Expression<Func<T>> expression)
{
    var name = ((MemberExpression)expression.Body).Member.Name;
    var value = expression.Compile()();
    return string.Format("{0} - {1}", name, value);
}

use:

Meth(() => YourObject.Property);

Great solution over here...

Passing properties by reference in C#

void GetString<T>(string input, T target, Expression<Func<T, string>> outExpr)
{
    if (!string.IsNullOrEmpty(input))
    {
        var expr = (MemberExpression) outExpr.Body;
        var prop = (PropertyInfo) expr.Member;
        prop.SetValue(target, input, null);
    }
}

void Main()
{
    var person = new Person();
    GetString("test", person, x => x.Name);
    Debug.Assert(person.Name == "test");
}

Why don't you use Linq for this? Like:

vehicles.OrderBy(v => v.maxSpeed).ToList();