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

按值传递引用类型的方法与返回结果的方法的区别及性能差异

按值传递引用类型的方法与返回结果的方法的区别及性能差异

在处理对象列表时,存在两种操作方式,由此产生疑问:按值传递引用类型的方法与返回结果的方法之间有什么区别?二者是否存在性能差异?

示例代码

public class SampleClass
{
    public int FirstNumber { get; set; }
    public int SecondNumber { get; set; }
}

public string MainFunction()
{
    var sampleClassesList = new List<SampleClass>
    {
        new SampleClass
        {
            FirstNumber = 1,
            SecondNumber = 2
        },
        new SampleClass
        {
            FirstNumber = 3,
            SecondNumber = 4
        }
    };

    //方式1 - 返回结果
    sampleClassesList = Calculate1(sampleClassesList);

    //方式2 - 按值传递引用类型
    Calculate2(sampleClassesList);

    return string.Empty;
}

public List<SampleClass> Calculate1(List<SampleClass> sampleClasses)
{
    foreach (var item in sampleClasses)
    {
        item.FirstNumber += item.FirstNumber;
        item.SecondNumber -= item.SecondNumber; 
    }
    return sampleClasses;
}

public void Calculate2(List<SampleClass> sampleClasses)
{
    foreach (var item in sampleClasses)
    {
        item.FirstNumber += item.FirstNumber;
        item.SecondNumber -= item.SecondNumber;
    }
}

核心区别

1. 语义与设计意图

  • 返回结果的方法(Calculate1):更贴合函数式编程风格,语义上强调“输入→处理→输出”的转换逻辑,调用者能直观感知到变量的更新(即使示例中返回的是原引用)。如果后续修改方法逻辑为创建新列表返回,调用方的代码无需大幅调整就能适配新的纯转换逻辑。
  • void方法(Calculate2):属于命令式编程风格,方法的核心意图是执行修改操作,直接作用于传入对象的内部状态,调用者无需接收返回值,更侧重“副作用”的产生。

2. 引用指向的可控性

C#中引用类型参数默认是按值传递(传递的是引用的副本),但两者在引用指向的处理上有差异:

  • Calculate1返回后重新赋值给变量,如果方法内部创建了新的List<SampleClass>实例(比如return sampleClasses.Select(...).ToList()),外部变量会指向新的对象;
  • Calculate2无论内部逻辑如何,都只会修改原列表中元素的状态,不会改变外部变量的引用指向——外部变量始终指向最初创建的那个List实例。

3. 调用灵活性

返回结果的方法支持链式调用,比如可以直接写:

sampleClassesList = Calculate1(FilterInvalidItems(sampleClassesList));

而void方法无法实现这种链式组合,必须拆分写成多步语句。


性能差异

在你的示例场景下,两种方式的性能几乎没有区别:

  • Calculate1多了一步返回引用并赋值的操作,但引用本质是一个内存地址指针(64位系统仅8字节),这个操作的CPU和内存开销可以完全忽略;
  • 两种方法的核心逻辑都是遍历List并修改元素属性,这部分是性能消耗的主要来源,两者的执行效率完全一致。

只有在极端场景下才会出现差异:

  • 如果Calculate1的逻辑改为创建新的List实例返回(而非返回原引用),会产生额外的内存分配和GC回收开销;而Calculate2直接修改原列表则没有这部分成本——但这是逻辑差异带来的性能区别,并非返回值本身的开销;
  • 从JIT编译优化的角度,两种写法都能被高效优化,不会出现明显的执行效率差距。

总结

选择哪种方式主要取决于代码的设计风格和业务逻辑需求:

  • 如果希望保持逻辑的纯净性(不修改原对象,返回新的处理结果),优先选择返回结果的方法;
  • 如果明确需要修改原对象的状态,使用void方法会更简洁直观。

性能上在常规业务场景下无需纠结,两者的差异微乎其微。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.08 20:25:17