C#学习笔记-方法参数、扩展方法

传值参数

  声明时不带修饰符的形参为值形参,相当于方法内的局部变量,初始化的值来自调用该方法时提供的实参。

  当传值参数为值类型时,值形参相当于只拷贝实参的副本,对与值形参的改动不会影响到实参。

  当传值参数为引用类型,并创建新对象覆盖形参时,对形参的修改同样不会影响实参。

  当传值参数为引用类型,且只操作对象,不创建新对象时,对形参的修改影响实参。一般把修改参数所引用的对象的值的操作称为副引用(side-effect)

class Program
{
    static void Main(string[] args)
    {
        Student stu = new Student();
        int y = 100;
        stu.AddOne(y);  //形参x拷贝实参y的值,修改x的值不会影响y
        Console.WriteLine(y);

        stu.Name = "Mosen";
        SomeMethod(stu);
        Console.WriteLine(stu.Name);

        UpdataObject(stu);
        Console.WriteLine("{0}, {1}", stu.GetHashCode(), stu.Name);
    }

    static void SomeMethod(Student stu)
    {
        stu = new Student() { Name="Tom"}; //此处stu指向新的Student对象
        Console.WriteLine(stu.Name);
    }

    static void UpdataObject(Student s)  //通过修改 s 更新实参 stu 的值
    {
        s.Name = "Owmt";
        Console.WriteLine("{0}, {1}", s.GetHashCode(), s.Name);
    }
}

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

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

引用参数

   引用形参是用 ref 修饰符修饰的形参。引用形参不创建新的存储位置,而是直接指向传进来的实参所指向的内存地址。变量在作为引用形参传递之前,须明确赋值。

class Program
{
    static void Swap(ref int x, ref int y) //使用ref修饰形参,对x、y的改动会影响Main方法中的x、y
    {
        int temp = x;
        x = y;
        y = temp;
    }

    static void IWantSideEffect(ref Student stu) //对stu赋值会影响到 outterStu 指向的实例数据
    {
        stu = new Student() { Name = "Tom" };
        Console.WriteLine("HashCode={0}, Name={1}", stu.GetHashCode(), stu.Name); 
    }

    static void SomeSideEffect(ref Student stu) //影响到 outterStu2 指向的实例数据的内容
    {
        stu.Name = "Tom";
        Console.WriteLine("HashCode={0}, Name={1}", stu.GetHashCode(), stu.Name);
    }

    static void Main(string[] args)
    {
        int x = 10;
        int y = 20;
        Swap(ref x, ref y);
        Console.WriteLine(x + " " + y);

        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}\n", outterStu.GetHashCode(), outterStu.Name);

        Student outterStu2 = new Student() { Name = "Tim" };
        Console.WriteLine("HashCode={0}, Name={1}", outterStu2.GetHashCode(), outterStu2.Name);
        Console.WriteLine("--------------");
        SomeSideEffect(ref outterStu2);
        Console.WriteLine("HashCode={0}, Name={1}", outterStu2.GetHashCode(), outterStu2.Name);


    }

}

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

输出参数 

  使用out修饰符声明的形参为输出形参,和引用形参类似,输出形参不创建新的存储位置,和实参指向同一内存位置。使用输出参数时,方法体内必须要有对输出变量进行赋值的操作。out修饰符显示指出,方法的副作用是通过参数向外输出值。

class Program
{
    static void Main(string[] args)
    {

        double x = 0;
        bool res = DoubleParse.TryParse("724", out x);
        if (res)
        {
            Console.WriteLine(x+1);
        }

        Student stu = null;

        bool res2 = StudentFactory.Create("Tim", 25, out stu);
        if(res2)
        {
            Console.WriteLine("Student {0}, Age is {1}", stu.Name, stu.Age);
        }

    }
}

class DoubleParse
{
    public static bool TryParse(string input, out double result)
    {
        try
        {
            result = Double.Parse(input);
            return true;
        }
        catch
        {
            result = 0;
            return false;
        }
    }
}

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();
        result.Name = stuName;
        result.Age = stuAge;

        return true;
    }
}

注:使用引用参数时,调用方法处的实参需要明确赋值,更倾向于对实参的值进行修改。而输出参数在调用方法之前不一定需要明确赋值,更倾向于调用方法后对实参进行赋值。语义上 ref 是“改变”,而 out 是为了“输出”。

数组参数

  形参列表的最后一个参数,用 params 修饰。

class Program
{
    static void Main(string[] args)
    {
        int res = CalculateSum(1,2,3,4,5); //不必提前声明数组,而是直接输入数组元素即可   
        Console.WriteLine(res);

        string str = "Tim;Tom,Amy.Lisa";
        string[] splitRes = str.Split(';', ',', '.');

        foreach (string s in splitRes)
        {
            Console.WriteLine(s);
        }
    }

    static int CalculateSum(params int[] intArray)
    {
        int sum = 0;
        foreach(var item in intArray)
        {
            sum += item;
        }

        return sum;
    }
}

具名参数

  可以提高代码可读性且参数的位置不受约束。

class Program
{
    static void Main(string[] args)
    {
        PrintInfo(age: 23, name:"Tim");
    }

    static void PrintInfo(string name, int age)
    {
        Console.WriteLine("Name: {0}\nAge: {1}", name, age);
    }
}

 可选参数

  参数具有默认值而变得“可选”。

class Program
{
    static void Main(string[] args)
    {
        PrintInfo();
    }

    static void PrintInfo(string name = "Tim", int age = 23)
    {
        Console.WriteLine("Name: {0}\nAge: {1}", name, age);
    }
}

扩展方法(this参数)

  用于为目标数据类型“追加”方法:

  1、方法必须是公有、静态(public static)。

  2、必须是形参列表中的第一个,由 this 修饰。

  3、必须由一个静态类(一般名为 xxxExtension)统一收纳相应的类型的扩展方法。

class Program
{
    static void Main(string[] args)
    {
        double x = 3.1415926;
        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;
    }
}

 

posted @   owmt  阅读(48)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 全程不用写代码,我用AI程序员写了一个飞机大战
· DeepSeek 开源周回顾「GitHub 热点速览」
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 记一次.NET内存居高不下排查解决与启示
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
点击右上角即可分享
微信分享提示