美文网首页
C#参数类型

C#参数类型

作者: 秦海波 | 来源:发表于2021-11-28 12:48 被阅读0次
C#.jpeg

一、按值参数传递

默认情况下C#中的参数默认按值传递,这是常用的方式。这意味着在将参数值传递给方法时将创建一份参数值的副本

  • 示例一
static void Foo (int p)
{
    p = p + 1;                          // +1
    Console.WriteLine ("p is " + p);    
}

static void Main()
{
    int x = 8;
    Foo (x);                            // 创建副本
    Console.WriteLine ("x is " + x);    // x is 8
}

  • 示例二

由于Foo (sb);是引用的一份副本,因此将他赋值为null不会把sb也赋值为null

static void Foo (StringBuilder fooSB)
{
    fooSB.Append ("test");
    fooSB = null;
}

static void Main()
{
    StringBuilder sb = new StringBuilder();
    Foo (sb);
    Console.WriteLine (sb.ToString());    // test
}

二、ref 修饰符

若按引用传递参数则应使用ref 参数修饰符。

  • 示例一

由于p和x指向同一块内存地址,给P赋值将改变x的值。ref 修饰符在声明和调用时都是必须的,这样可以清楚的表明程序如何执行

static void Foo (ref int p)
{
    p = p + 1;               // Increment p by 1
    Console.WriteLine (p);   // Write p to screen
}

static void Main()
{
    int x = 8;
    Foo (ref  x);            // Ask Foo to deal directly with x
    Console.WriteLine (x);   // x is now 9
}

  • 示例二

ref修饰符对于实现交换方法是必要的

static void Swap (ref string a, ref string b)
{
    string temp = a;
    a = b;
    b = temp;
}
    
static void Main()
{
    string x = "Penn";
    string y = "Teller";
    Swap (ref x, ref y);
    Console.WriteLine (x);   // Teller
    Console.WriteLine (y);   // Penn
}

三、out 修饰符

out参数和ref参数类似

  • 无需在传入参数之前进行赋值
  • 必须在函数结束之前赋值
    out 修饰符通常用于获得方法的多个返回值
  • 示例一

与ref参数一样out参数按引用传递

static void Split (string name, out string firstNames, out string lastName)
{
    int i = name.LastIndexOf (' ');
    firstNames = name.Substring (0, i);
    lastName   = name.Substring (i + 1);
}
    
static void Main()
{
    string a, b;
    Split ("Stevie Ray Vaughn", out a, out b);
    Console.WriteLine (a);                      // Stevie Ray
    Console.WriteLine (b);                      // Vaughn
}

out变量及丢弃变量

从C#7.0开始允许在调用含有out参数的方法时直接声明变量
因此示例一种Main方法可做如下简化

  • 示例二
static void Main()
{
    Split ("Stevie Ray Vaughan", out string a, out string b);
    Console.WriteLine (a);                      // Stevie Ray
    Console.WriteLine (b);                      // Vaughan
}

当调用含有多个out参数的方法时,若并不关注所有参数的值,那么可以用下划线来丢弃那些不感兴趣的参数
处于兼容性考虑如果作用域内已经有一个名为[_]的变量那么丢弃符号失效

Split ("Stevie Ray Vaughan", out string x, out _);   // Discard the 2nd param
Console.WriteLine (x);

按引用传递的含义

按引用传递参数是为现存变量的存储位置起一个别名而不是创建一个新的存储位置。

public class Test
{
    static int x;
    
    static void Main()
    {
        Foo(out x);
    }
    static void Foo(out int y){
        Console.WriteLine (x);
        y = 10;
        Console.WriteLine (x); 
    }
}

四、in 修饰符

in参数和ref参数类似,但是前者的参数值无法在方法内修改(修改会产生编译时错误)
这个修饰符非常适合向方法传递大型值类型对象,因此编译时不仅可以避免在参数传递时对参数进行拷贝操作而造成开销,还可以保护参数的原始值不会被修改。

in修饰符是重载的一个重要部分

void Main()
{
    SomeBigStruct x = default;
    
    Foo (x);      // Calls the first overload
    Foo (in x);   // Calls the second overload

    Bar (x);      // OK (calls the 'in' overload)
    Bar (in x);   // OK (calls the 'in' overload)
}

void Foo (SomeBigStruct a)    => "Foo".Dump();
void Foo (in SomeBigStruct a) => "in Foo".Dump();

void Bar (in SomeBigStruct a) => "in Bar".Dump();

struct SomeBigStruct
{
    public decimal A, B, C, D, E, F, G;
}

五、params 修饰符

该修饰符只能修饰方法的最后一个参数,使方法接收任意数量的指定类型的参数。参数类型必须声明为数组

static int Sum (params int[] ints)
{
    int sum = 0;
    for (int i = 0; i < ints.Length; i++)
        sum += ints[i];                       // Increase sum by ints[i]
    return sum;
}
    
static void Main()
{
    int total = Sum (1, 2, 3, 4);
    Console.WriteLine (total);              // 10
    
    // The call to Sum above is equivalent to:
    int total2 = Sum (new int[] { 1, 2, 3, 4 } );
}

可选参数

参数声明中提供默认值,这个参数就是可选参数

static void Foo (int x = 23) { Console.WriteLine (x); }

static void Main()
{
    Foo();      // 23
    Foo (23);   // 23  (equivalent to above call)
}

命名参数

除了用位置确定参数,还可以用名称来确定参数
命名参数能够以任意顺序出现

static void Foo (int x, int y) { Console.WriteLine (x + ", " + y); }

static void Main()
{
    Foo (x:1, y:2);  // 1, 2
    Foo (y:2, x:1);  // 1, 2   (semantically same as above)
    
    // You can mix named and positional arguments:
    Foo (1, y:2);
}

相关文章

  • C#参数类型

    一、按值参数传递 默认情况下C#中的参数默认按值传递,这是常用的方式。这意味着在将参数值传递给方法时将创建一份参数...

  • C#与C++类型互转

    一、C#调用DLL文件时参数对应表 二、C#调用C++编写的DLL函数, 以及各种类型的参数传递 如果函数只有传入...

  • C#参数类型总结

    图1来自《图解C#》 ref 和 outC#中的ref 和C++中的&运算符功能类似,但又有所不同。ref是传引用...

  • 引用类型的参数加不加Ref的区别

    问题描述:引用类型的参数加不加Ref的区别? 解答 备注:C#高级编程(第10版) 3.6.1 ref参数(92页...

  • 参数的 in out in/out 修饰

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

  • C#调用MS SQL存储过程时输出参数小数被舍掉问题

    起因 昨天在项目维护中发现C#调用存储过程时sql输出参数数据类型为numeric(18,4),C#对应Decim...

  • [转]C#进阶系列——WebApi 接口参数不再困惑:传参详解

    转自 懒得安分的 C#进阶系列——WebApi 接口参数不再困惑:传参详解 阅读目录 一、get请求基础类型参数实...

  • C#委托学习笔记

    什么是委托 委托(Delegates)是C#中一种特别的类型,它可以引用具有指定参数类型和返回类型的方法。比如pu...

  • C# where用法

    C# where用法 where 子句用于指定类型约束,这些约束可以作为泛型声明中定义的类型参数的变量。1.接口约...

  • C#语言入门详解006

    006 C#类型、变量与对象详解 目录 *什么是类型*类型在C#语言中的作用*C#语言的类型系统*变量、对象与内存...

网友评论

      本文标题:C#参数类型

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