首页 > 编程语言 > 详细

C#语言入门(10)传值/输出/引用/数组/具名/可选参数,扩展方法

时间:2021-08-02 09:39:37      阅读:26      评论:0      收藏:0      [点我收藏+]

1、传值参数

(1)值类型

声明时不带修饰符的形参是值形参。一个值形参对应于一个局部变量,只是它的初始值来自该方法调用所提供的相应实参。
技术分享图片

注意:(1)值参数创建变量的副本(2)对值参数的操作永远不影响变量的值

```c#
namespace ConsoleApp2
{
class Program
{
static void Main(string[] args)
{
Student stu = new Student();
int y = 100;
stu.AddOne(y);
Console.WriteLine(y);
}

}

class Student
{
    public void AddOne(int x)
    {
        x += 1;
        Console.WriteLine(x);
    }

}

}

### (2)引用类型
- 新创建对象
![image.png](https://s2.51cto.com/images/20210801/1627799799407720.png?x-oss-process=image/watermark,size_14,text_QDUxQ1RP5Y2a5a6i,color_FFFFFF,t_100,g_se,x_10,y_10,shadow_20,type_ZmFuZ3poZW5naGVpdGk=)
```c#
namespace ConsoleApp2
{
    class Program
    {
        static void Main(string[] args)
        {
            Student stu = new Student() { Name = "Tim" };
            SomeMethod(stu);
            Console.WriteLine("{0},{1}",stu.GetHashCode(),stu.Name);
        }
        static void SomeMethod(Student stu)
        {
            stu = new Student() { Name = "Tom" };
            Console.WriteLine("{0},{1}", stu.GetHashCode(),stu.Name);
        }
    }

    class Student
    {
       public string Name { get; set; }      
    }

}
  • 只操作对象,不创建新对象
    技术分享图片

    注意:对象还是那个对象,但对象里的值(字段/属性)已经改变
    ```c#
    namespace ConsoleApp2
    {
    class Program
    {
    static void Main(string[] args)
    {
    Student stu = new Student() { Name = "Tim" };
    UpdateObiect(stu);
    Console.WriteLine("HashCode={0},Name={1}", stu.GetHashCode(),stu.Name);
    }
    static void UpdateObiect(Student stu)
    {
    stu.Name="Tom";
    Console.WriteLine("HashCode={0},Name={1}", stu.GetHashCode(),stu.Name);
    }
    }

    class Student
    {
    public string Name { get; set; }
    }

}

## 2、引用参数

引用形参是用ref修饰符声明的形参。与值形参不同,引用形参并不创建新的存储位置。相反,引用形参表示的存储位置恰是在方法调用中作为实参给出的那个变量所表示的存储位置。变量在可以作为引用形参传递之前,必须先明确赋值。
### (1)值类型
![image.png](https://s2.51cto.com/images/20210801/1627813568333572.png?x-oss-process=image/watermark,size_14,text_QDUxQ1RP5Y2a5a6i,color_FFFFFF,t_100,g_se,x_10,y_10,shadow_20,type_ZmFuZ3poZW5naGVpdGk=)
>注意:(1)引用参数并不创建变量的副本
       (2)使用ref修饰符显式指出——此方法的副作用是改变实际参数的值

```c#
namespace ConsoleApp2
{
    class Program
    {
        static void Main(string[] args)
        {
            int y = 1;
            IWantSideEffect(ref y);
            Console.WriteLine(y);
        }
        static void IWantSideEffect(ref int x)
        {
            x+=1;
        }
    }

(2)引用类型

  • 创建新变量
    技术分享图片
    ```c#
    namespace ConsoleApp2
    {
    class Program
    {
    static void Main(string[] args)
    {
    Student outterStu = new Student() { Name = "Tim" };
    Console.WriteLine("HashCode={0},Name={1}", outterStu.GetHashCode(), outterStu.Name);
    Console.WriteLine("---------------------------");
    IWantSideEffect(ref outterStu);
    Console.WriteLine("HashCode={0},Name={1}", outterStu.GetHashCode(), outterStu.Name);
    }
    static void IWantSideEffect(ref Student stu)
    {
    stu = new Student() { Name = "Tom" };
    Console.WriteLine("HashCode={0},Name={1}",stu.GetHashCode(),stu.Name);
    }
    }

    class Student
    {
    public string Name { get; set; }
    }

}

- 不创建新对象,只改变对象值
![image.png](https://s2.51cto.com/images/20210801/1627825014543788.png?x-oss-process=image/watermark,size_14,text_QDUxQ1RP5Y2a5a6i,color_FFFFFF,t_100,g_se,x_10,y_10,shadow_20,type_ZmFuZ3poZW5naGVpdGk=)
>注意:此时与传值参数在效果上并无不同,但机理不一样,有些面试题会考到

```c#
namespace ConsoleApp2
{
    class Program
    {
        static void Main(string[] args)
        {
            Student outterStu = new Student() { Name = "Tim" };

            Console.WriteLine(" Hashcod={0},Name={1}", outterStu.GetHashCode(), outterStu.Name);
            Console.WriteLine("--------------------------------");
            SomeSideEffect(ref outterStu);
            Console.WriteLine(" Hashcod={0},Name={1}", outterStu.GetHashCode(), outterStu.Name);
        }
        static void SomeSideEffect(ref Student stu)
        {
            stu.Name = "Tom";
            Console.WriteLine(" Hashcod={0},Name={1}", stu.GetHashCode(), stu.Name);
        }
    }

    class Student
    {
       public string Name { get; set; }      
    }

}

技术分享图片

3、输出参数

用out修饰符声明的形参是输出形参。类似于引用形参,输出形参不创建新的存储位置。相反,输出形参表示的存储位置恰是在该方法调用中作为实参给出的那个变量所表示的存储位置。变量在可以作为输出形参传递之前不一定需要明确赋值。在方法返回之前,该方法的每个输出形参都必须明确赋值。

  • 值类型
    技术分享图片

(1) 输出参数并不创建变量的副本
(2) 方法体内必需要有对输出变量的赋值的操作
(3) 使用out修饰符显式指出-------此方法的副作用是通过参数向外输出值
(4) 从语义上来讲----------ref是为了“改变" , out是为了"输出”

```c#
class Program
{
static void Main(string[] args)
{
Console.WriteLine("Please input first number:");
string arg1 = Console.ReadLine();
double x = 0;
bool b1 = double.TryParse(arg1, out x);
if (b1==false)
{
Console.WriteLine("input error!");
return;
}
Console.WriteLine("Please input second number:");
string arg2 = Console.ReadLine();
double y = 0;
bool b2 = double.TryParse(arg2, out y);
if (b2 == false)
{
Console.WriteLine("input error!");
return;
}
double z = x + y;
Console.WriteLine("{0}+{1}={2}",x,y,z);
}

其中TryParse方法
```c#
 class DoubleParser
    {
       public static bool TryParse(string input,out double result)
        {
            try
            {
                result = double.Parse(input);
                return true;
            }
            catch 
            {
                result = 0;
                return false;
            }
        }
    }

}
  • 引用类型
    技术分享图片
    ```c#
    namespace ConsoleApp2
    {
    class Program
    {
    static void Main(string[] args)
    {
    Student stu = null;
    bool b = StudentFactory.Create("Tim", 34, out stu);
    if (b==true)
    {
    Console.WriteLine("Student {0},age is {1}.",stu.Name,stu.Age);
    }
    }

    }

    class Student
    {
    public int Age { get; set; }
    public string Name{ get; set; }
    }
    class StudentFactory
    {
    public static bool Create(string stuName,int stuAge,out Student result)
    {
    result = null;
    if (string.IsNullOrEmpty(stuName))
    {
    return false;
    }
    if (stuAge<20||stuAge>80)
    {
    return false;
    }
    result = new Student() { Name = stuName, Age = stuAge };
    return true;
    }
    }

}

## 4、数组参数
- 必需是形参列表中的最后一个,由params修饰
- 举例: String.Format方法和String.Split方法。
```c#
  class Program
    {
        static void Main(string[] args)//无需声明一个数组
        {
            int result = CalculateSum(1,2,3);
            Console.WriteLine(result);
        }
        static int CalculateSum(params int[] intArray)
        {
            int sum = 0;
            foreach (var item in intArray)
            {
                sum += item;
            }
            return sum;
        }

    }

```c#
static void Main(string[] args)
{
string str = "Tim;Tom,Amy.Lisa";
string[] result = str.Split(‘;‘, ‘,‘, ‘.‘);
foreach (var name in result)
{
Console.WriteLine(name);
}
}

![image.png](https://s2.51cto.com/images/20210801/1627830074966754.png?x-oss-process=image/watermark,size_14,text_QDUxQ1RP5Y2a5a6i,color_FFFFFF,t_100,g_se,x_10,y_10,shadow_20,type_ZmFuZ3poZW5naGVpdGk=)

## 5、具名参数
- 参数的位置不要再受约束
```c#
 class Program
    {
        static void Main(string[] args)
        {
            PrintInfo(name: "Tim", age: 34);
        }
        static void PrintInfo(string name,int age)
        {
            Console.WriteLine("Hello {0},You are {1}",name,age);
        }

    }

6、可选参数

  • 参数因为具有默认值而变得"可选”
  • 不推荐使用可选参数

7、扩展方法

  • 方法必需是公有、静态的,即被public static所修饰
  • 必需是形参列表中的第一个,由this修饰
  • 必需由一个静态类( 一般类名为Some TypeExtension )来统一收纳对
  • SomeType类型的扩展方法
  • 举例: LINQ方法
    ```c#
    class Program
    {
    static void Main(string[] args)
    {
    double x = 3.14159;
    double y = x.Round(4);
    Console.WriteLine(y);
    }
    }
    static class DoubleExtension
    {
    public static double Round(this double input, int digits)
    {
    double result = Math.Round(input, digits);
    return result;
    }
    }
    ```c#
    class Program
    {
        static void Main(string[] args)
        {
            List<int> myList = new List<int>() { 11, 12, 13, 14, 15 };
            bool result = myList.All(i=>i>10);
            Console.WriteLine(result);
        }            
    }

    8、各种参数使用场景总结

  • 传值参数:参数的默认传递方式
  • 输出参数:用于除返回值外还需要输出的场景
  • 引用参数:用于需要修改实际参数值的场景
  • 数组参数:用于简化方法的调用
  • 具名参数:提高可读性
  • 可选参数:参数拥有默认值
  • 扩展方法( this参数) : 为目标数据类型"追加”方法

C#语言入门(10)传值/输出/引用/数组/具名/可选参数,扩展方法

原文:https://blog.51cto.com/u_15296868/3245905

(0)
(0)
   
举报
评论 一句话评论(0
分享档案
最新文章
教程昨日排行
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!