cstimothy18-传值/引用/输出/数组/具名/可选参数,扩展方法

018 传值、输出、引用、数组、具名、可选参数、扩展方法 · 语雀C#语言入门详解 传值 输出 引用 数组 具名 可选参...https://www.yuque.com/yuejiangliu/dotnet/timothy-csharp-018


应用场景:

传值参数-参数的默认传递方式

引用参数ref-用于需要修改实际参数值的场景

输出参数out-用于除返回值外还需要输出的场景

数组参数-用于简化方法的调用

具名参数-提高可读性

可选参数-参数拥有默认值

this参数-扩展方法-为目标数据类型追加方法

 传值参数-不带修饰符的形参

1.1传值参数-值类型

值参数创建变量的副本

对值参数的操作永远不影响变量的值

cpp-形参是实参的一份临时拷贝,对形参的操作不会影响实参

//1.1传值参数-值类型
namespace cstimothy181
{
    class Program
    {
        static void Main(string[] args)
        {
            Student stu = new Student();
            int y = 1;
            stu.AddOne(y);//2
            Console.WriteLine(y);//1
        }
    }
    class Student
    {
        public void AddOne(int x)
        {
            x++;
            Console.WriteLine(x);
        }
    }
}

实线框表示是1个副本

1.2传值参数-引用类型,并且创建新对象-workless

引用类型的变量和实例是分开的

引用类型变量存储的值为实例在堆内存上的地址

对引用类型变量赋值,=new,创建了新对象

object类有GetHashCode()方法

得到hashcode的代表对象唯一值

//1.2传值参数-引用类型,并且创建新对象-workless
namespace cstimothy182
{
    class Program
    {
        static void Main(string[] args)
        {
            Student stu = new Student() { Name = "Tim" };
            SomeMethod(stu);//Tim,58225482
            Console.WriteLine($"{stu.Name},{stu.GetHashCode()}");//Tim,54267293
        }
        static void SomeMethod(Student stu)
        {
            stu = new Student() { Name = "Tim" };
            Console.WriteLine($"{stu.Name},{stu.GetHashCode()}");
        }
    }
    class Student
    {
        public string Name { get; set; }
    }
}

1.3传值参数-引用类型,只操作对象不创建新对象

作为1个方法而言,方法的输出主要靠返回值

修改参数所引用的对象的值的操作-方法副作用side-effect-编程避免

//1.3传值参数-引用类型,只操作对象,不创建新对象
//side-effect
namespace cstimothy183
{
    class Program
    {
        static void Main(string[] args)
        {
            Student stu = new Student() { Name = "Tim" };
            Console.WriteLine($"{stu.Name},{stu.GetHashCode()}");//Tim,58225482
            UpdateObject(stu);//Tim,58225482
            Console.WriteLine($"{stu.Name},{stu.GetHashCode()}");//Tim,58225482
        }
        static void UpdateObject(Student stu)
        {
            stu.Name = "Tim";
            Console.WriteLine($"{stu.Name},{stu.GetHashCode()}");
        }
    }
    class Student
    {
        public string Name { get; set; }
    }
}

 

引用参数ref-用ref修饰声明的形参

调用时要加ref关键字

变量在传参之前,必须先明确赋值

 

2.1引用参数-值类型


//2.1引用参数-值类型
namespace cstimothy184
{
    class Program
    {
        static void Main(string[] args)
        {
            int y = 1;
            IWantSideEffect(ref y);//2
            Console.WriteLine(y);//2
        }
        static void IWantSideEffect(ref int x)
        {
            x++;
            Console.WriteLine(x);
        }
    }
}

虚线框-不创建副本

使用ref关键字显式指出-此方法的副作用是改变实参的值

 2.2引用参数-引用类型,创建新对象

//2.2引用参数-引用类型,创建新对象
namespace cstimothy185
{
    class Program
    {
        static void Main(string[] args)
        {
            Student stu = new Student() { Name = "Tim" };
            Console.WriteLine($"{stu.Name},{stu.GetHashCode()}");//Tim,58225482
            IWantSideEffect(ref stu);//Tim,54267293
            Console.WriteLine($"{stu.Name},{stu.GetHashCode()}");//Tim,54267293
        }
        static void IWantSideEffect(ref Student stu)
        {
            stu = new Student() { Name = "Tim" };
            Console.WriteLine($"{stu.Name},{stu.GetHashCode()}");
        }
    }
    class Student
    {
        public string Name { get; set; }
    }
}

 

2.3引用参数-引用类型,不创建新对象只改变对象值

此时效果和传值参数效果相同,但是在内存机理上不同:

传值参数:实参和形参指向的内存地址不同,但是这两个内存地址里存储着一个相同的内存地址-对象在堆内存中的地址

引用参数:实参和形参指向的内存地址相同,这个内存地址存储着对象在堆内存中的地址

//2.3引用参数-引用类型,不创建新对象只改变对象值
namespace cstimothy186
{
    class Program
    {
        static void Main(string[] args)
        {
            Student stu = new Student() { Name = "Tim" };
            Console.WriteLine($"{stu.Name},{stu.GetHashCode()}");//Tim,58225482
            IWantSideEffect(ref stu);//Tim,58225482
            Console.WriteLine($"{stu.Name},{stu.GetHashCode()}");//Tim,58225482
        }
        static void IWantSideEffect(ref Student stu)
        {
            stu.Name = "Tim";
            Console.WriteLine($"{stu.Name},{stu.GetHashCode()}");
        }
    }
    class Student
    {
        public string Name { get; set; }
    }
}

 

输出参数out

变量在作为实参传参之前不一定需要明确赋值

在方法返回之前。这个方法的每个输出形参都必须明确赋值

 

3.1输出参数-值类型

将字符串解析为int/double类型

Parse-解析不成功会抛异常

TryParse

//3.1输出参数-值类型
namespace cstimothy187
{
    class Program
    {
        static void Main(string[] args)
        {
            string arg1 = Console.ReadLine();
            double x = 0;
            bool b1 = double.TryParse(arg1, out x);
            if (b1 == false)
            {
                Console.WriteLine("input error");
                return;
            }
            string arg2 = Console.ReadLine();
            double y = 0;
            bool b2 = double.TryParse(arg2, out y);
            if (b2 == false)
            {
                Console.WriteLine("input error");
                return;
            }
            Console.WriteLine(x + y);
        }
    }
}
namespace cstimothy188
{
    class Program
    {
        static void Main(string[] args)
        {
            double x = 100;
            bool b = DoubleParser.TryParse("abc", out x);
            if (b==true)
            {
                Console.WriteLine(x);
            }
            else
            {
                Console.WriteLine(x);
            }
        }
    }
    class DoubleParser
    {
        public static bool TryParse(string input, out double ret)
        {
            try
            {
                ret = double.Parse(input);
                return true;
            }
            catch
            {
                ret = 0;
                return false;
            }
        }
    }
}

虚线框-不创建副本

方法体内必须有对输出变量赋值的操作

使用out修饰符显式指出-此方法的副作用是通过参数向外输出值

ref-改变

out-输出

 3.2输出参数-引用类型

//3.2输出参数 - 引用类型
namespace cstimothy189
{
    class Program
    {
        static void Main(string[] args)
        {
            Student stu = null;
            bool b = StudentFactory.Create("Tim", 34, out stu);
            if (b==true)
            {
                Console.WriteLine($"{stu.Name},{stu.Age},{DateTime.UtcNow}");
            }
        }
    }
    class Student
    {
        public int Age { get; set; }
        public string Name { get; set; }
    }
    class StudentFactory
    {
        public static bool Create(string name, int age, out Student stu)
        {
            stu = null;
            if (string.IsNullOrEmpty(name))
            {
                return false;
            }
            if (age<20||age>80)
            {
                return false;
            }
            stu = new Student() { Name = name, Age = age };
            return true;
        }
    }
}

 

4.数组参数

必须为形参列表的最后1个,由params修饰

String string?

String.Format

String.Split

//数组参数
namespace cstimothy1810
{
    class Program
    {
        static void Main(string[] args)
        {
            int[] nums1 = new int[] { 1, 2, 3 };
            Console.WriteLine(CalculateSum(nums1));
            Console.WriteLine(CalculateSum(2, 3, 4));
        }
        static int CalculateSum(params int[] intArray)
        {
            int sum = 0;
            foreach (var item in intArray)
            {
                sum += item;
            }
            return sum;
        }
    }
}
//string.split方法
namespace cstimothy1811
{
    class Program
    {
        static void Main(string[] args)
        {
            string str = "131,1917;2731";
            //string[]-字符串数组
            string[] ret = str.Split(';', ',');//和顺序无关
            foreach (var item in ret)
            {
                Console.WriteLine(item);
            }
        }
    }
}

 

5.具名参数

-参数的位置不再受约束

-提高代码可读性

//具名参数
namespace cstimothy1812
{
    class Program
    {
        static void Main(string[] args)
        {
            PrintInfo("Tim", 34);
            PrintInfo(age: 25, name: "Eric");
        }
        static void PrintInfo(string name, int age)
        {
            Console.WriteLine($"{name},{age}");
        }
    }
}

 

6.可选参数

参数因为具有默认值而变得可选

不推荐使用

//可选参数
namespace cstimothy1813
{
    class Program
    {
        static void Main(string[] args)
        {
            PrintInfo();
        }
        static void PrintInfo(string name = "Tim", int age = 34)
        {
            Console.WriteLine($"{name},{age}");
        }
    }
}

 7.this参数-扩展方法

//this参数-扩展方法
namespace cstimothy1814
{
    class Program
    {
        static void Main(string[] args)
        {
            double x1 = 3.14159;
            double y1 = Math.Round(x1, 4);
            double x2 = 3.14159;
            double y2 = x1.Round(4);
        }
    }
    static class DoubleExtension
    {
        public static double Round(this double input, int digits)
        {
            return Math.Round(input, digits);
        }
    }
}
//LINQ
using System.Collections.Generic;
using System.Linq;
namespace cstimothy1815
{
    class Program
    {
        static void Main(string[] args)
        {
            List<int> myList1= new List<int>() { 11, 12, 13, 14, 15 };
            bool ret1 = ALLGreaterThanTen(myList1);
            Console.WriteLine(ret1);
            //LINQ
            //ALL是Enumerable静态类的泛型方法
            List<int> myList2 = new List<int>() { 11, 12, 13, 14, 15 };
            bool ret2 = myList2.All(i => i > 10);
            Console.WriteLine(ret2);
        }
        static bool ALLGreaterThanTen(List<int> intList)
        {
            foreach (var item in intList)
            {
                if (item<=10)
                {
                    return false;
                }
            }
            return true;
        }
    }
}

 

 

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值