为什么有out参数存在?

一、原因?

=》

如果要返回单个元素,可以直接返回

复制代码
int getParms()
{}

如果返回多个同类型元素,可以使用数组,

复制代码
public int[] GetNumbers()
{
    int[] numbers = { 1, 2, 3, 4, 5 };
    return numbers;
}

如果要返回不同类型的元素,怎么办?

比如:返回一个bool类型,一个int类型。out参数的功能就是在此(不说复合类型struct)

复制代码
// C# 1.0时期(2002年),没有好的多返回值方案
public bool TryParse(string s, out int result)
{
    // 当时这是唯一的选择
}

二、现代C#中更好的替代方案

1. 元组(C# 7.0+,推荐)

复制代码
// 替代out参数的最佳选择
public (bool Success, int Result) TryParseInt(string input)
{
    if (int.TryParse(input, out int result))
        return (true, result);
    return (false, 0);
}

// 调用更清晰
var (success, value) = TryParseInt("123");
if (success)
{
    Console.WriteLine($"值为: {value}");
}

2. 记录类型/自定义类型(语义清晰)

复制代码
public record ParseResult(bool Success, int Value);

public ParseResult ParseString(string input)
{
    if (int.TryParse(input, out int result))
        return new ParseResult(true, result);
    return new ParseResult(false, 0);
}

// 使用
var result = ParseString("123");
if (result.Success)
{
    // 使用 result.Value
}

3. 模式匹配(C# 8.0+)

复制代码
public int? TryParseInt(string input)
{
    return int.TryParse(input, out int result) ? result : null;
}

// 使用
if (TryParseInt("123") is int value)
{
    Console.WriteLine(value);
}

4. 返回对象或集合

复制代码
// 返回复杂对象
public class CalculationResult
{
    public int Quotient { get; init; }
    public int Remainder { get; init; }
    public bool IsValid { get; init; }
}

public CalculationResult Divide(int a, int b)
{
    if (b == 0)
        return new CalculationResult { IsValid = false };
    
    return new CalculationResult
    {
        Quotient = a / b,
        Remainder = a % b,
        IsValid = true
    };
}

什么时候仍然需要 使用out

1. 维护现有API的兼容性

复制代码
// 必须与现有的TryParse模式保持一致
public interface IMyParser
{
    bool TryParse(string input, out MyType result);
}

2. 性能极端敏感的代码

复制代码
// 极少数情况,避免分配额外的内存
public void ProcessSpan(ReadOnlySpan<byte> source, out int processedBytes)
{
    // 高度优化的代码
    processedBytes = CalculateBytes(source);
}

3. 与外部代码交互

复制代码
// 调用Windows API或COM组件
[DllImport("user32.dll")]
public static extern bool GetCursorPos(out Point lpPoint);

现代建议

避免使用out的情况

复制代码
// 不推荐 - 使用元组更好
public void Calculate(int a, int b, 
    out int sum, out int diff, out int product, out int quotient)
{
    sum = a + b;
    diff = a - b;
    product = a * b;
    quotient = a / b;
}

推荐的做法

复制代码
// 推荐1:使用元组
public (int Sum, int Difference, int Product, int Quotient) 
    Calculate(int a, int b)
{
    return (a + b, a - b, a * b, a / b);
}

// 推荐2:使用模式匹配
public int? SafeParse(string input) => 
    int.TryParse(input, out int result) ? result : null;

// 推荐3:使用记录类型
public record CalculationResults(
    int Sum, int Difference, int Product, int Quotient);

总结

直接回答你的问题 :C#中并不一定要用 out参数。它主要是:

  1. 历史遗留:早期版本的C#缺少更好的多返回值方案

  2. 兼容性保持与现有.NET API的一致性

  3. 特殊情况:性能极端敏感或与外部代码交互

现代C#开发建议

  • 优先使用元组(C# 7.0+)

  • 考虑记录类型获得更好的语义

  • 只在必须时使用out(如实现特定接口或保持兼容)

  • 永远不要为了"性能"而盲目使用out(先测量,再优化)

out参数在现代C#中更像是一种"向后兼容"的特性,而不是首选的编程模式。新的代码库应该优先考虑使用更现代、更清晰的替代方案。

相关推荐
lly2024061 小时前
Bootstrap 警告框
开发语言
2601_949146531 小时前
C语言语音通知接口接入教程:如何使用C语言直接调用语音预警API
c语言·开发语言
曹牧1 小时前
Spring Boot:如何测试Java Controller中的POST请求?
java·开发语言
KYGALYX2 小时前
服务异步通信
开发语言·后端·微服务·ruby
zmzb01032 小时前
C++课后习题训练记录Day98
开发语言·c++
懒人咖2 小时前
缺料分析时携带用料清单的二开字段
c#·金蝶云星空
猫头虎2 小时前
如何排查并解决项目启动时报错Error encountered while processing: java.io.IOException: closed 的问题
java·开发语言·jvm·spring boot·python·开源·maven
YUJIANYUE3 小时前
PHP纹路验证码
开发语言·php
仟濹3 小时前
【Java基础】多态 | 打卡day2
java·开发语言
孞㐑¥3 小时前
算法——BFS
开发语言·c++·经验分享·笔记·算法