Is there a way to supply a name to a function that then returns the value of either the field or property on a given object with that name? I tried to work around it with the null-coalesce operator, but apparently that doesn't like different types (which is also a bit weird to me because null is null). I could separate it it out into if nulls, but there has to be a better way to do this. Here is my function, and the two lines with Comparison objects don't compile, but I will leave them in there to show what I am trying to do.

private void SortByMemberName<T>(List<T> list, string memberName, bool ascending)
{
   Type type = typeof (T);
   MemberInfo info = type.GetField(memberName) ?? type.GetProperty(memberName);

   if (info == null)
   {
        throw new Exception("Member name supplied is neither a field nor property of type " + type.FullName);
   }

   Comparison<T> asc = (t1, t2) => ((IComparable) info.GetValue(t1)).CompareTo(info.GetValue(t2));
   Comparison<T> desc = (t1, t2) => ((IComparable) info.GetValue(t2)).CompareTo(info.GetValue(t1));

    list.Sort(ascending ? asc : desc);
}

I have heard of something called dynamic LINQ that could be used, but for the sake of learning, I am doing it my way.

有帮助吗?

解决方案

Change this line:

MemberInfo info = type.GetField(memberName) ?? type.GetProperty(memberName);

to this:

MemberInfo info = type.GetField(memberName) as MemberInfo ??
    type.GetProperty(memberName) as MemberInfo;

because there's no implicit cast to the base class when using the ternary operator like that. The ternary requires that the types of all outputs be the same.

其他提示

As of C# 9.0, this will finally be possible:

Target typed ?? and ?:

Sometimes conditional ?? and ?: expressions don’t have an obvious shared type between the branches. Such cases fail today, but C# 9.0 will allow them if there’s a target type that both branches convert to:

Person person = student ?? customer; // Shared base type
int? result = b ? 0 : null; // nullable value type

That means the code block in the question will also compile without errors; it will 'see' that FieldInfo and PropertyInfo have a shared base type, MemberInfo.

MemberInfo info = type.GetField(memberName) ?? type.GetProperty(memberName);
许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top