You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

获取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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.19 02:17:15