背景#
var x = A?.B?.C?.D?.E;
如果 A、B、C、D 或 E 中的任何一个为 null
,则 x
将被计算为 null
。
那么,有没有办法找到哪个成员的值为 null
?
方法一:条件检查#
对每个成员使用一系列条件检查:
String findNullMember(A a) {
if (a is null) return "A";
if (a.B is null) return "A.B";
if (a.B.C is null) return "A.B.C";
if (a.B.C.D is null) return "A.B.C.D";
if (a.B.C.D.E is null) return "A.B.C.D.E";
return "";
}
来自:
- https://www.reddit.com/r/csharp/comments/1b9ojdu/comment/ktx2p2p/?utm_source=share&utm_medium=web2x&context=3
- https://www.reddit.com/r/csharp/comments/1b9ojdu/comment/ktx3fvn/?utm_source=share&utm_medium=web2x&context=3
方法二:Expression 表达式#
可以使用表达式来生成字符串,但无法在表达式主体中使用 null 条件运算符 (?.)。
static string FindNullMember<T>(Expression<Func<T>> expression)
{
Stack<MemberExpression> path = new();
Expression? body = expression.Body;
while (body is MemberExpression prop)
{
path.Push(prop);
body = prop.Expression;
}
object? rootObject;
switch (body)
{
case null:
{
// Accessing a static property:
rootObject = null;
break;
}
case ConstantExpression c:
{
// Accessing an instance property:
rootObject = c.Value;
if (rootObject is null) return string.Empty;
break;
}
default:
{
throw new ArgumentException($"Unsupported expression: {expression}", nameof(expression));
}
}
StringBuilder result = new();
foreach (MemberExpression prop in path)
{
if (result.Length != 0) result.Append('.');
result.Append(prop.Member.Name);
switch (prop.Member)
{
case PropertyInfo pi:
{
rootObject = pi.GetValue(rootObject);
break;
}
case FieldInfo fi:
{
rootObject = fi.GetValue(rootObject);
break;
}
default:
{
result.Append("# Unsupported member type: ").Append(prop.Member.GetType().Name).Append('#');
rootObject = null;
break;
}
}
if (rootObject is null) break;
}
return result.ToString();
}
用法:
string x = FindNullMember(() => A.B.C.D.E);