美文网首页
C# 方法参数(params、in、ref、out)

C# 方法参数(params、in、ref、out)

作者: 86a262e62b0b | 来源:发表于2019-08-12 11:53 被阅读0次

参考转载文档:https://docs.microsoft.com/zh-cn/dotnet/csharp/language-reference/keywords/method-parameters

总结概括:

  • params 指定此参数采用可变数量的参数。
  • in 指定此参数由引用传递,但只由调用方法读取。
  • ref 指定此参数由引用传递,可能由调用方法读取或写入。
  • out 指定此参数由引用传递,由调用方法写入。

一. in、ref、out

相同点:

  • 指定此参数由引用传递
  • in、ref 和 out 关键字不在用于决定重载的方法签名中区分。 因此,如果一个方法唯一区别是采用 ref 或 in 参数,而另一个方法采用 out 参数,则无法重载这两个方法。例如,以下代码将不会编译:
class CS0663_Example
{
    // Compiler error CS0663: "Cannot define overloaded 
    // methods that differ only on in, ref and out".
    public void SampleMethod(in int i) { }
    public void SampleMethod(ref int i) { }
}

存在 in 时可以重载:

class InOverloads
{
    public void SampleMethod(in int i) { }
    public void SampleMethod(int i) { }
}
  • 不能将 refinout 关键字用于以下几种方法:
  1. 异步方法,通过使用 async 修饰符定义。
  2. 迭代器方法,包括 yield returnyield break 语句。

1. in

特点:
  • C# 7.2 及更高版本
  • in 参数传递的变量在方法调用中传递之前必须进行初始化
  • 它类似于 ref 或 out 关键字,不同之处在于 in 参数无法通过调用的方法进行修改。例如:
int readonlyArgument = 44;
InArgExample(readonlyArgument);
Console.WriteLine(readonlyArgument);     // value is still 44

void InArgExample(in int number)
{
    // Uncomment the following line to see error CS8331
    //number = 19;
}

使用优点:

  • 定义使用 in 参数的方法是一项潜在的性能优化。 某些 struct 类型参数可能很大,在紧凑的循环或关键代码路径中调用方法时,复制这些结构的成本就很高。 方法声明 in 参数以指定参数可能按引用安全传递,因为所调用的方法不修改该参数的状态。 按引用传递这些参数可以避免(可能产生的)高昂的复制成本。

注:为了简化操作,前面的代码将 int 用作参数类型。 因为大多数新式计算机中的引用都比 int 大,所以将单个 int 作为只读引用传递没有任何好处。

补充:

关于重载的规则请参考文档:in
以下代码阐释了这些规则:

static void Method(in int argument)
{
    // implementation removed
}

Method(5); // OK, temporary variable created.
Method(5L); // CS1503: no implicit conversion from long to int
short s = 0;
Method(s); // OK, temporary int created with the value 0
Method(in s); // CS1503: cannot convert from in short to in int
int i = 42;
Method(i); // passed by readonly reference
Method(in i); // passed by readonly reference, explicitly using `in`
static void Method(int argument)
{
    // implementation removed
}

static void Method(in int argument)
{
    // implementation removed
}

Method(5); // Calls overload passed by value
Method(5L); // CS1503: no implicit conversion from long to int
short s = 0;
Method(s); // Calls overload passed by value.
Method(in s); // CS1503: cannot convert from in short to in int
int i = 42;
Method(i); // Calls overload passed by value
Method(in i); // passed by readonly reference, explicitly using `in`

2. ref

  • 必须先经过初始化

  • 传递到 ref 形参的实参必须先经过初始化这与 out 形参不同。

  • 使用 ref 参数,方法定义和调用方法均必须显式使用 ref 关键字:

void Method(ref int refArgument)
{
    refArgument = refArgument + 44;
}

int number = 1;
Method(ref number);
Console.WriteLine(number);
// Output: 45
  • 关于ref返回值,详细参考文档

3. out

  • 不需要初始化
  • 若要使用 out 参数,方法定义和调用方法均必须显式使用 out 关键字。
  • 作为 out 参数传递的变量在传递之前不必进行初始化。 但是,被调用的方法需要在返回之前赋一个值。
void OutArgExample(out int number)
{
    number = 44;
}

二. params

  1. 特点:
  • 使用 params 关键字可以指定采用数目可变的参数的方法参数。
  • 可以发送逗号分隔的指定类型的参数列表,或指定类型的参数数组。 还可以不发送参数。 如果未发送任何参数,则 params 列表的长度为零。
  • 声明的 params 参数类型必须是一维数组,如以下示例所示。 否则,发生编译器错误 CS0225
  • 在方法声明中的 params 关键字之后不允许有任何其他参数,并且在方法声明中只允许有一个 params 关键字。
public class MyClass
{
    public static void UseParams(params int[] list)
    {
        for (int i = 0; i < list.Length; i++)
        {
            Console.Write(list[i] + " ");
        }
        Console.WriteLine();
    }

    public static void UseParams2(params object[] list)
    {
        for (int i = 0; i < list.Length; i++)
        {
            Console.Write(list[i] + " ");
        }
        Console.WriteLine();
    }

    static void Main()
    {
        // You can send a comma-separated list of arguments of the 
        // specified type.
        UseParams(1, 2, 3, 4);
        UseParams2(1, 'a', "test");

        // A params parameter accepts zero or more arguments.
        // The following calling statement displays only a blank line.
        UseParams2();

        // An array argument can be passed, as long as the array
        // type matches the parameter type of the method being called.
        int[] myIntArray = { 5, 6, 7, 8, 9 };
        UseParams(myIntArray);

        object[] myObjArray = { 2, 'b', "test", "again" };
        UseParams2(myObjArray);

        // The following call causes a compiler error because the object
        // array cannot be converted into an integer array.
        //UseParams(myObjArray);

        // The following call does not cause an error, but the entire 
        // integer array becomes the first element of the params array.
        UseParams2(myIntArray);
    }
}
/*
Output:
    1 2 3 4
    1 a test
           
    5 6 7 8 9
    2 b test again
    System.Int32[]
*/

注:
不要混淆通过引用传递的概念与引用类型的概念。 这两种概念是不同的。 无论方法参数是值类型还是引用类型,均可由 ref 修改。 当通过引用传递时,不会对值类型装箱。

相关文章

  • C# 方法参数(params、in、ref、out)

    参考转载文档:https://docs.microsoft.com/zh-cn/dotnet/csharp/lan...

  • Unity 加载资源

    在Resources文件夹里面放入资源。加载如: 扩展方法-扩展系统组件ref 、out、params参数区别 r...

  • C#参数传递,ref、out和params

    最近换工作面试,遇到了一个基础的坑,是关于C#参数传递的问题。 参数传递主要分两种,值传递和引用传递。实际C#还提...

  • Out And Ref

    在C#中Out和Ref使用方法基本一样。Out使用时其实参数可以不赋值,在使用时在实参数前面加上Out,如下:Ou...

  • c#(14) 数据类型 方法参数ref out params

    8yue 24 数据类型 值类型和引用类型区别 值类型 引用类型 形参和实参 (通常情况下我们带参数方法就是把 实...

  • 17.03.12 .Net基础(三)

    out参数 out参数侧重于在函数中返回多个值 out参数要求必须在方法的内部为其赋值 ref参数 ref参数侧重...

  • Unity中有关C#的几个要点

    大致总结下C#中几个常见知识点的个人理解,以对基础已经有所了解为前提。 ref/out 区别:ref参数需要在传入...

  • C# ref & out

    1. What is ref & out ? 参数传递时按引用传递参数 2.Why need ref & out ...

  • out, ref关键字

    功能 在C#中,ref与out是很特殊的两个关键字。使用它们,可以使参数按照引用来传递。 总的来说,通常我们向方法...

  • 参数的 in out in/out 修饰

    知识点 in out in/out IN 一个函数,默认情况下,参数是 in 类型,即传入参数,以C# 中的方法为...

网友评论

      本文标题:C# 方法参数(params、in、ref、out)

      本文链接:https://www.haomeiwen.com/subject/hdgyjctx.html