获取MethodInfo时遇致命错误,求C#链式调用简化错误检查方案
简化C#链式调用中的空值/空集合检查方案
我是C#新手,正在尝试简化代码。下面这段带分步错误检查的MethodInfo获取代码能正常运行,但第二种链式调用的写法因为缺少对SkipWhile等步骤的空值/空集合检查,偶尔会导致程序崩溃,想请教有没有更简便的错误检查方式?
分步检查的可运行代码
MethodInfo[] methods1 = type.GetMethods(BindingFlags.Instance | BindingFlags.NonPublic) .Where(x => x.IsAssembly != true && x.ReturnType == typeof(void) && x.GetParameters().Length == 2 && x.GetParameters()[0].ParameterType == typeof(object) && x.GetParameters()[1].ParameterType == typeof(EventArgs)) .ToArray(); foreach (MethodInfo method in methods1) { MethodBody methodBody = method.GetMethodBody(); if (methodBody == null) continue; byte[] array = methodBody.GetILAsByteArray(); if (array.Length == 0) continue; byte[] take = array.Take(7).ToArray(); if (take.Length == 0) continue; byte[] skip = take.SkipWhile(b => b != 0x80).ToArray(); if (skip.Length == 0) continue; bool last = skip.Last().Equals(0x14); }
易崩溃的链式调用代码
// 偶尔崩溃,因为缺少SkipWhile等步骤的空值/空集合检查 MethodInfo[] methods = type.GetMethods(BindingFlags.Instance | BindingFlags.NonPublic) .Where(x => x.IsAssembly != true && x.ReturnType == typeof(void) && x.GetParameters().Length == 2 && x.GetParameters()[0].ParameterType == typeof(object) && x.GetParameters()[1].ParameterType == typeof(EventArgs)) .Where(m => m .GetMethodBody() .GetILAsByteArray() .Take(7) .SkipWhile(b => b != 0x80) .Last().Equals(0x14)) .ToArray();
解决方案
1. 用LastOrDefault()替代Last(),结合空值检查
链式调用崩溃的核心是:GetMethodBody()返回null、GetILAsByteArray()返回空数组,或SkipWhile()后无剩余元素时,调用Last()会抛出异常。改用LastOrDefault()并增加前置检查即可避免:
MethodInfo[] methods = type.GetMethods(BindingFlags.Instance | BindingFlags.NonPublic) .Where(x => !x.IsAssembly && x.ReturnType == typeof(void) && x.GetParameters().Length == 2 && x.GetParameters()[0].ParameterType == typeof(object) && x.GetParameters()[1].ParameterType == typeof(EventArgs)) .Where(m => { var methodBody = m.GetMethodBody(); if (methodBody == null) return false; var ilBytes = methodBody.GetILAsByteArray(); return ilBytes != null && ilBytes.Length > 0 ? ilBytes.Take(7) .SkipWhile(b => b != 0x80) .LastOrDefault() == 0x14 : false; }) .ToArray();
2. 提取辅助方法,保持链式清爽
把空值检查和IL验证逻辑抽成单独方法,让主调用链更简洁:
// 辅助方法:封装验证逻辑 private static bool MatchesILPattern(MethodInfo method) { var methodBody = method.GetMethodBody(); if (methodBody == null) return false; var ilBytes = methodBody.GetILAsByteArray(); if (ilBytes == null || ilBytes.Length == 0) return false; var filteredBytes = ilBytes.Take(7).SkipWhile(b => b != 0x80); return filteredBytes.Any() && filteredBytes.Last() == 0x14; } // 主调用链 MethodInfo[] methods = type.GetMethods(BindingFlags.Instance | BindingFlags.NonPublic) .Where(x => !x.IsAssembly && x.ReturnType == typeof(void) && x.GetParameters().Length == 2 && x.GetParameters()[0].ParameterType == typeof(object) && x.GetParameters()[1].ParameterType == typeof(EventArgs)) .Where(MatchesILPattern) .ToArray();
3. 空传播运算符+条件表达式的紧凑写法
如果偏好更简洁的链式风格,可用C# 6+的空传播运算符?.,利用null与数值比较返回false的特性简化:
MethodInfo[] methods = type.GetMethods(BindingFlags.Instance | BindingFlags.NonPublic) .Where(x => !x.IsAssembly && x.ReturnType == typeof(void) && x.GetParameters().Length == 2 && x.GetParameters()[0].ParameterType == typeof(object) && x.GetParameters()[1].ParameterType == typeof(EventArgs)) .Where(m => m.GetMethodBody()?.GetILAsByteArray()? .Take(7) .SkipWhile(b => b != 0x80) .LastOrDefault() == 0x14) .ToArray();
内容的提问来源于stack exchange,提问作者genibec746
相关产品推荐
相关产品推荐

