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;
}
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 全程不用写代码,我用AI程序员写了一个飞机大战
· DeepSeek 开源周回顾「GitHub 热点速览」
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 记一次.NET内存居高不下排查解决与启示
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了