C#方法参数传递

今日份主要内容:

  1. 构造函数执行顺序
  2. 析构函数
  3. 方法参数传递:值传递,引用传递
  4. ref、out、in关键字
  5. 递归
  6. 可变参数params
  7. foreach语句

构造函数执行顺序

子类中调用父类的方法

  • ​ 构造函数什么时候执行?

    ​ 实例化的时候执行,new Cat();

  • ​ 调用子类无参构造函数的时候,会默认调用父类无参构造函数。通过调用子类 有参构造函数,同样默认会调用父类无参构造函数。

  • ​ 那如何调用父类的有参构造函数呢?

    ​ 在子类的有参构造函数里可以使用 : base(参数),明确调用父类有参构造函数。

	
	public class Animal : Cat
	
	public Animal():base()//子类默认调用基类的无参数构造函数。相当于:base()。
    {
        Console.WriteLine("子类Animal的无参构造函数");
    }
    
	public Animal(int color, string name) : base(color, name)
	{
		Console.WriteLine("子类Animal的有参构造函数");
	}
//base充当了基类的实例

​ 构造函数的执行顺序:构造函数在执行时,先进入子类构造函数,再进入父类构造函数,依次向上,直到0bject对象;

​ 出来的时候,先把Object对象的构造函数执行完,再回到父类。父类执行完,再回到子类,依次向下,直到最终的子类,形成了U型结构。

​ 参考:构造函数 - C# | Microsoft Learn

C#中子类调用父类的实现方法 - phpStudy (xp.cn)

析构函数

  • ​ GC在回收类的实例时,和终结器(析构函数)有关系。析构函数用来释放对象。
  • ​ 因为在C#释放对象一般是自动,不建议手动。所以析构函数不常用。
  • ​ 定义的格式: ~+类名,不能有修饰符。只有一个析构函数。开发者无法调用它,一般是GC调用。

​ 参考:终结器 - C# | Microsoft Learn

方法参数传递

方法参数可以通过值传递、引用传递和输出参数传递。

	
	static void Main(string[] args)
	{
    	// 方法参数传递时有两种传递方式:1。值传递  2。引用传递
    	Class1 cls = new Class1();

		// a,b实参,即实际参数,使用方法时,实参传递到形参中。
		int a = 1;
		int b = 2;
		// 值传递特点:默认情况,实参传递到形参中,方法内修改形参后,不会影响实参。
		// 值传递,默认实参向形参传递过去的是值。
		cls.Add(a, b);
		Console.WriteLine($"a:{a},b:{b}");

		Console.WriteLine("---------------------");

		// 字符串虽然是引用类型,但字符串比较特殊,在实参向形参传递参数时,和值类型的默认效果一样。即方法内修改形参不会影响实参。
		string s1 = "value1";
		string s2 = "value2";
		cls.Add(s1, s2);
		Console.WriteLine($"s1:{s1},s2:{s2}");

		Console.WriteLine("---------------------");

		// 引用传递特点:默认情况,方法内修改了形参(修改实例指向的地址),会影响实参。
		// 如果修改了某个实例的相关属性(即没有修改地址,只修改堆上某个空间中的值),不会影响实参。
		// 引用传递,默认实参向形参传递是地址。画图理解
		Person p1 = new Person() { Id = 1, Name = "name1" };
		Person p2 = new Person() { Id = 2, Name = "name2" };
		cls.Add(p1, p2);
		Console.WriteLine($"p1:{p1},p2:{p2}");

		Console.ReadKey();
    }


	public class Class1
	{
    	// x,y形参,即形式参数,占个位置,方法使用时,实参传递到形参中。
    	public void Add(int x, int y)
    	{
        	// 由于值类型在栈上分配空间,值也在栈上,和堆没有关系。
        	// 所以在方法内修改了栈上的值,不会影响实参。
        	x = 20;
        	y = 20;
        	Console.WriteLine($"x:{x},y{y}");
    	}

    	public void Add(string x, string y)
    	{
        	// x,y重新指向堆上的某个空间,形参s1,s2的在堆上的空间没有变。
        	x = "hello";
        	y = "world";
        	Console.WriteLine($"x:{x},y:{y}");
    	}

    	public void Add(Person x, Person y)
    	{
        	// 修改了某个实例的相关属性
        	x.Id = 10;
        	x.Name = "ABC";
        	// 修改实例指向的地址
        	y = new Person() { Id = 11, Name = "DEF" };
        	Console.WriteLine($"x:{x},y:{y}");
    	}
	}

ref、out、in关键字

ref:表示引用传递。通过这个关键字,方法可以直接修改引用所指向的原始变量的值。

out:主要用于从方法中输出一个值。调用方法前,变量可以不初始化,但在方法内必须给它赋值。

in:从 C# 7.2 开始引入,它确保参数在方法内不会被修改,提供了一种明确表达参数只读意图的方式。

	
public class Class1
{
	public void Method1(int a, bool flag)
	{
    	a = 100;
    	flag = true;
    	Console.WriteLine($"值类型修改后的值:a={a},flag={flag}");
	}
    
	// ref==reference引用,指针,地址   ref是输入参数
	// 虽然形参的数据类型是值类型,但添加ref关键字,实参向形参传递的不再变量值,是变量地址。
	// 向ref形参传递参数时,实参必须初始化。
	// ref 传入的变量必须初始化,但是在内部可改可不改 
	public void Method2(ref int a, ref bool flag)
	{
    	a = 100;
    	flag = true;
    	Console.WriteLine($"值类型修改后的值:a={a},flag={flag}");
	}

	// out输出参数
	// 方法的返回值只能有一个,通过return返回。
	// 方法输出的结果可以有多个,return只是返回结果的一种方式,而输出参数out是另外一种方式。
	// 输出参数在方法内必须赋初值。即:out 传入的变量不用初始化,但是在内部必须修改该值
	// 向out形参传递参数时,实参不必初始化。
    // 可变参数,默认值,后面不可以跟必选参数,out没有这个限定。
	public int Method3(int a, out string x, out long y, int z)
	{
    	x = "hello world";
    	y = 200;
    	return 100;
	}

	// in和out最大不同,in传递过来的参数,不能修改。而out必须修改。ref想改就改,不想改不改。
	// in传递过来的参数是只读的。
	public string Method4(int a, in string x, in long y, int z)
	{
    	//x = "hello world";  // 报错
    	//y = 200;
    	return x + 100 + y;
	}
}

static void Main(string[] args)
{

    Class1 cls = new Class1();
    //向ref形参传递参数时,实参必须初始化。
    int x = 1;
    bool f = false;
    cls.Method1(x, f);
    Console.WriteLine($"x={x},f={f}");

    Console.WriteLine("-----------------");

    cls.Method2(ref x, ref f);
    Console.WriteLine($"x={x},f={f}");

    Console.WriteLine("-----------------");
    //向out形参传递参数时,实参不必初始化。
    string xx = "abc";
    long yy = 100;
    int result = cls.Method3(0, out xx, out yy, 0);

    Console.WriteLine($"xx={xx},yy={yy}");
    Console.WriteLine($"返回值={result}");

    Console.WriteLine("-----------------");

    // 向in形参传递参数时,必须初始化。由于方法不让修改in形参,所以实参不受影响
    string xxx = "abc";
    long yyy = 100;
    string result1 = cls.Method4(0, in xxx, in yyy, 0);
    Console.WriteLine($"xxx={xxx},yyy={yyy}");
    Console.WriteLine($"返回值={result1}");

    Console.ReadKey();
}

昨天作业(新知识:递归,foreach,for和foreach区别,可变参数params)

递归

​ 递归:函数的自调用。函数内部再调用函数自身,就形成递归。形成了循环。

​ C# 循环,递归,迭代,可枚举的都含有循环。数组就带有迭代器。

​ 递归必须要有return或者break,跳出循环。

 public static int Factorial(int n)
 {
     /*if (n == 0)
         return 1;
     else
         return n * Factorial(n - 1);*/

	 return n == 0 ? 1 : n * Factorial(n - 1);

 }

可变参数params

关键字params,parameters 参数,表示可变参数,即参数个数不固定。

可变参数后面不能加上必填参数,可变参数只能有一个。


class Program
{
    static void PrintParams(params int[] numbers) 
    {
        foreach (var num in numbers)
        {
            Console.Write(num + " ");
        }
        Console.WriteLine();
    }

    static void Main()
    {
        PrintParams(1, 2, 3);
        PrintParams(4, 5, 6, 7);
        Console.WriteLine(Math.Sum1(new float[] { 1,2}));
    }
}


      
        public static float Sum1(float[] nums = null)// 把参数传递一个数组,参数个数也可以不固定,但不包括0,除非带有默认值null。为null,后面的不调用。
        {
            if (nums == null) return 0;
            float sum = 0;
            for (int i = 0; i < nums?.Length; i++)
            {
                sum += nums[i];
            }
            return sum;
        }

​ 可变参数具有以下一些重要意义:

  1. 灵活性:它允许方法接受不同数量的参数,使方法在使用时更加灵活和通用,而无需针对不同数量的参数定义多个方法版本。

  2. 简洁性:减少了代码的重复和复杂性,开发人员可以更简洁地处理参数数量不确定的情况。

  3. 易用性:对于调用者来说,传递参数变得更加方便,无需特意去构建特定结构的参数集合。

  4. 适应性:能更好地适应不同的场景和需求,使得方法可以根据实际情况处理各种数量的输入。

foreach语句

类似于for语句,foreach专门用来循环对象的,循环用来遍历数组、集合等的,但是只能用于遍历形式,不能改变循环目标。

  • for循环在循环中是可以更改循环目标的。

  • foreach的循环性能比较高。

  • foreach的应用范围没有for的广。

  • 字符串也可以用foreach循环,它实现了可枚举的接口。

  • for中可以拿循环对象的索引,而foreach不能拿循环对象的索引。

posted @   海域  阅读(32)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· AI 智能体引爆开源社区「GitHub 热点速览」
· C#/.NET/.NET Core技术前沿周刊 | 第 29 期(2025年3.1-3.9)
· 从HTTP原因短语缺失研究HTTP/2和HTTP/3的设计差异
点击右上角即可分享
微信分享提示