C# 方法

方法

方法的结构

方法是一块具有名称的代码

方法是类的函数成员, 方法主要有两个部分, 方法头和方法体

void MyMethod()
{
	Console.WriteLine("First");
	Console.WriteLine("Last");
}

方法体的块中可以包含:
本地变量
控制流结构
方法调用
内嵌的块

static void Main()
{
	int myInt = 3;					//本地变量
	while(myInt > 0)    			//控制流结构
	{
		--myInt;
		PrintMyMessage();			//方法调用
	}
}

本地变量

具有块作用域,无链接, 时间从声明到块结束的属性。

static void Main()
{
	int myInt = 15;
	SomeClass sc = new SomeClass();
	...
}

实例字段从被创建开始, 到不被访问时结束, 具有默认值, 类的所有字段存储在堆中
本地变量没有隐式初始化, 值类型存储在栈中, 引用类型引用存储在栈中, 数据存储在堆中

类型推断和var关键字

var表示任何可以从初始化的右边推断出的类型

static void Main()
{
	var total = 15;
	var mec = new MyExcellentClass();
	...
}

var只能用于本地变量,, 不能用于字段
只能在包含初始化的变量声明中使用。

嵌套块中的本地变量

C#无论嵌套级别如何, 都不能在嵌套块中声明相同名称的变量。

本地常量

在类型之加关键字const即可

const Type Identifier = Value;

控制流

与c基本相同

方法调用

call方法与invoke方法是同义的

class MyClass
{
	void PrintdateAndTime();
	{
		DataTime dt = DataTime.Now;		//获取当前的日期和时间
		Console.WriteLine("{0}", dt);
	}
	static void Main()
	{
		MyClass mc = new Myclass();
		mc.PrintDataAndTime();
	}
}

返回值

与c相同

int GetHour()
{
	DataTime dt = DataTime.Now;
	int hour = dt.Hour;				//获取小时数

	return hour;
}

也可以返回用户定义类型的对象

MyClass method3()
{
	MyClass mc = new MyClass ();
	....
	return mc;
}
class MyClass
{
	public int GetHour()
	{
		DataTime dt = DataTime.Now;
		int hour = dt.Hour;
		return hour;
	}
}
class Program
{
	static void Main()
	{
		MyClass mc = new MyClass();
		Console.WriteLine("Hour: {0}", mc.GetHour());
	}
}

return; 后面不跟返回值返回void

class MyClass
{
	void TimeUpdate()
	{
	DataTime dt = DataTime.Now;
	if (dt.Hour < 12)
		return;
	Console.WriteLine("It's afternoon!");
	}
	static void Main()
	{
		MyClass mc = new MyClass();
		pc.TimeUpdate();
	}
}

参数

output参数除外, 其他参数都需要初始化, 其余与c相同

class MyClass
{
	public int Sum(int x, int y)
	{
		return x + y;
	}
	public float Avg(float input1, float input2)
	{
			return (input1 + input2) \2.0F; 
	}
}
class Program
{
	static void Main()
	{
		MyClass myT = new MyClass();
		int someInt =  6;
		
		Console.WriteLine
			("Newsflash: Sum: {0} and {1} is {2}",
				 5, someInt, myT.Sum(5, someInt));
		Console.WriteLine
			("Newsflash : Avg : {0} and {1} is  {2}", 5, someInt, myT.Avg(5, someInt));
	}
}

引用参数

使用引用参数时必须在方法的声明和调用中都使用ref修饰符。
引用参数实参必须是变量
个人理解: 有点像查不到地址的指针, 说白了形参引用了实参的地址, 而不是值

class MyClass
{
	public int Val = 20;
}
class Program
{
	static void MyMethod(ref MyClass f1, ref int f2)
	{
		f1.val  = f1.val + 5;
		f2 = f2 + 5;
	}
	static void Main()
	{
		MyClass a1 = new MyClass();
		int a2 = 10;
		MyMethod(ref a1, ref a2);
	}
}

输出参数

用于从方法体内部把数据传出到调用代码, 非常类似于引用参数,使用修饰符out表示
但是不需要在调用方法之前赋值, 而是在方法读取该参数之前必须被赋值

class MyClass
{
	pblic int Val = 20;
}
class Program
{
	static void MyMethod(out MyClass f1, out int f2)
	{
		f1 = new MyClass();
		f1.val = 25;
		f2 = 15;
	}
	static void Main()
	{
		MyClass a1 = null;
		int a2;
		MyMethod(out a1, out a2);
	}
}

参数数组

参数数组允许** 零个或多个实参对应一个特殊的形参**
在数据类型之前使用params即可
需要在数据类型后放一个空的方括号
如果有, 必须是列表的最后一个(有点像c中的可变参数stdarg)
值参数的声明与调用不需要修饰符
引用参数和输出参数时需要修饰符

延伸式

这种形式调用中使用分离的实参

void ListInts(params int [] inVals){...}


...
ListInts();
ListInts(1, 2, 3);
ListInts(4, 5, 6, 7);


```csharp
class MyClass
{
    public void ListInts(params int[] inVals)
    {
        if ((inVals != null) && (inVals.Length != 0))
            for (int i = 0; i < inVals.Length; i++)
            {
                inVals[i] = inVals[i] * 10;
                System.Console.WriteLine("{0} ", inVals[i]);
            }
    }
}
class Program
{
    static void Main()
    {
        int first = 5, second = 6, third = 7;

        MyClass mc = new MyClass();
        mc.ListInts(first, second, third);
        System.Console.WriteLine("{0}, {1}, {2}", first, second, third);
    }
}

数组做实参

class MyClass
{
    public void ListInts(params int[] inVals)
    {
        if ((inVals != null) && (inVals.Length != 0))
            for (int i = 0; i < inVals.Length; i++)
            {
                inVals[i] = inVals[i] * 10;
                System.Console.WriteLine("{0} ", inVals[i]);
            }
    }
}

static void Main()
{
	int [] MyArr = new int[] {5, 6, 7}; //创建并初始化数组, 存在堆中

	MyClass mc = new MyClass();
	mc.ListInts(MyArr);
	foreach (int x in MyArr)
		Console.WriteLine("{0}", x);
}

方法重载

一个类中可以有一个以上的方法拥有相同的名称, 这称为方法重载(method overload)
使用相同名称的每个方法必须有一个和其它方法不相同的签名(signature)。
签名由以下组成

  1. 方法的名称
  2. 参数的数目
  3. 参数的数据类型和顺序
  4. 参数修饰符

形参的名称不是签名的一部分

命名参数

显式指定形参的名字, 就可以以任意顺序在方法调用中列出实参

class MyClass
{
	public int Calc(int a, int a, int b, int c);
	{return (a + b) * c}
	static void Main()
	{
		MyClass mc = new MyClass();
		int result = mc.Calc(c: 2, a: 4, b: 3);
		Console.WriteLine("{0}", result);
	}
}

调用时既可以使用位置参数也可以使用命名参数,但位置参数必须提前列出

可选参数

需要在方法声明时为参数提供默认值

class MyClass
{
	public int Calc(int a, int b = 3)
	{
		return a + b;
	}
	static void Main()
	{
		MyClass mc = new MyClass();
		int r0 = mc.Calc(5, 6);
		int r1 = mc.Calc(5);				//b使用默认值

		Console.WriteLine("{0}, {1}", r0, r1);
	}
}

所有必填参数必须在可选参数之前声明, 有params参数的必须在可选参数之后声明

栈帧

调用方法时, 内存从栈的顶部开始分配, 保存和方法关联的一些数据项, 这块内存称之为方法的栈帧(stack frame)。
方法退出时, 整个栈帧从栈上弹出, 也叫做栈展开(unwind)。

递归

计算阶乘数的代码如下

int Factorial(int inValue)
{
	if (inValue <= 1)
		return inValue;
	else
		return inValue * Factorial (inValue - 1);
}
class Program
{
	public void Count(int inVal)
	{
		if (inVal == 0)
			return;
		Count(intVal - 1);			//再一次调用
		Console.WriteLine("{0}", inVal);
	}
	static void Main()
	{
		Program pr = new Program();
		pr.Count(3);	
	}
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值