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

如何将带可选参数的方法参数传递给另一个带可选参数的方法?

如何在C#中传递可选参数而不硬编码目标方法的默认值

方案1:使用方法重载(适合参数数量少的场景)

直接为G方法提供多个重载版本,对应是否传递可选参数的情况,完全复用F方法的默认值,无需额外判断:

public class FClass{
    public void F(string input1, string input2 = "my default string"){
        // Do stuff
    }
}

public class GClass{
    private readonly FClass _fClass = new FClass();

    // 无可选参数的重载:调用F的单参数版本,让F用自身默认值
    public void G(string input1){
        var someVar = input1; // 示例业务逻辑
        _fClass.F(someVar);
    }

    // 带可选参数的重载:直接传递参数给F
    public void G(string input1, string input2){
        var someVar = input1; // 示例业务逻辑
        _fClass.F(someVar, input2);
    }
}

优点:

  • 代码直观,无冗余判断逻辑
  • 完全遵循FClass的默认值定义,不用在GClass重复维护
  • 性能最优,无额外开销

缺点:

  • 可选参数数量多的时候,需要创建2^n个重载版本,代码冗余度高

方案2:利用[CallerArgumentExpression]检测参数是否被显式传入(C# 10+)

用C# 10引入的[CallerArgumentExpression]特性,直接判断用户是否显式传入了可选参数,不用额外类型包装:

public class FClass{
    public void F(string input1, string input2 = "my default string"){
        // Do stuff
    }
}

public class GClass{
    private readonly FClass _fClass = new FClass();

    public void G(string input1, string input2 = default, 
                  [CallerArgumentExpression(nameof(input2))] string input2Expr = null){
        var someVar = input1; // 示例业务逻辑
        // 只要input2被显式传入(哪怕值是null),input2Expr就不为空
        if(input2Expr != null){
            _fClass.F(someVar, input2);
        } else {
            _fClass.F(someVar);
        }
    }
}

优点:

  • 无需额外类型或重载,代码简洁
  • 精准区分“未传入参数”和“传入参数值为默认值”的场景
  • 完全复用FClass的默认值定义

缺点:

  • 仅支持C# 10及以上版本
  • 多参数场景下要为每个可选参数添加对应的[CallerArgumentExpression]参数

方案3:自定义Optional<T>类型(兼容所有C#版本)

自己封装一个可选类型,专门标记参数的“是否传入”状态,而非仅依赖参数值:

// 自定义可选类型
public struct Optional<T>
{
    public bool HasValue { get; }
    public T Value { get; }

    private Optional(T value)
    {
        HasValue = true;
        Value = value;
    }

    // 允许隐式转换,调用时不用手动包装参数
    public static implicit operator Optional<T>(T value) => new Optional<T>(value);
    // 定义空实例,代表未传入参数
    public static readonly Optional<T> Empty = new Optional<T>();
}

public class FClass{
    public void F(string input1, string input2 = "my default string"){
        // Do stuff
    }
}

public class GClass{
    private readonly FClass _fClass = new FClass();

    public void G(string input1, Optional<string> input2 = default){
        var someVar = input1; // 示例业务逻辑
        if(input2.HasValue){
            _fClass.F(someVar, input2.Value);
        } else {
            _fClass.F(someVar);
        }
    }
}

调用示例:

var g = new GClass();
g.G("test"); // 不传入input2,F用自身默认值
g.G("test", "custom value"); // 传入input2,直接传递给F

优点:

  • 兼容所有C#版本
  • 清晰区分参数是否被传入,不受默认值影响
  • 多参数场景下只需替换参数类型,不用大量重载

缺点:

  • 需要自定义类型(也可以用第三方NuGet包如Optional)

方案4:使用反射(不推荐,仅作补充)

如果参数数量极多且无法用上述方案,可以通过反射动态构建调用,根据参数是否传入决定传递哪些值:

public class GClass{
    private readonly FClass _fClass = new FClass();
    private readonly MethodInfo _fMethod = typeof(FClass).GetMethod(nameof(FClass.F))!;

    public void G(string input1, string input2 = default){
        var someVar = input1; // 示例业务逻辑
        var parameters = new List<object> { someVar };
        // 仅当input2被传入时添加参数(注意:如果F的默认值不是null,这个判断逻辑要调整)
        if(input2 != default){
            parameters.Add(input2);
        }
        _fMethod.Invoke(_fClass, parameters.ToArray());
    }
}

优点:

  • 参数数量变化时不用修改调用逻辑

缺点:

  • 反射性能开销大,不适合高频调用场景
  • 编译时无类型检查,容易出错
  • 代码可读性差

内容的提问来源于stack exchange,提问作者Shark32

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.17 08:09:54