背景#
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:
{
// 存取靜態屬性:
rootObject = null;
break;
}
case ConstantExpression c:
{
// 存取實例屬性:
rootObject = c.Value;
if (rootObject is null) return string.Empty;
break;
}
default:
{
throw new ArgumentException($"不支援的表達式:{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("# 不支援的成員類型:").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);