//栈--存储局部变量和参数的内存块。
//逻辑上,栈会在函数进入和退出时增加或减少。
static int Factorial(int x) //每一次进入这个方法的时候,就在栈上分配一个新的int,而每一次离开这个方法,就会释放一个int。
{
if (x == 0) return 1;
return x * Factorial(x - 1);
}
static void Main(string[] args)
{
//堆--保存对象(例如引用类型的实例)的内存块。
//新创建的对象会分配在堆上并返回其引用。
//程序执行过程中,堆就被新创建的对象不断填充。.NET运行时的垃圾回收器会定期从堆上释放对象。
StringBuilder ref1=new StringBuilder("obj1");
Console.WriteLine(ref1); //ref1在后续没有使用的情况下可立即被垃圾回收器释放
StringBuilder ref2 = new StringBuilder("obj2");
StringBuilder ref3 = ref2; //此处将ref2的引用复制给ref3,虽然ref2之后不再使用,但是由于ref3保持着同一个StringBuilder对象的引用,因此在ref3使用完毕前它不会被垃圾回收器回收
Console.WriteLine(ref3);
//值类型的实例(和对象的引用)就存储在变量声明的地方。
//如果声明为类的字段或数组的元素,则该实例会存储在堆上。
//静态字段也会存储在堆上。与分配在堆上的对象(可以被垃圾回收)不同,这些变量一直存活直至应用程序域结束。
//明确赋值:
//局部变量在读取之前必须赋值
//使用方法时必须提供函数的实际参数
//运行时将自动初始化其他变量(例如字段和数组元素)。
//以下示例将产生编译时错误
//int x;
//Console.WriteLine(x); //使用了未赋值的局部变量x
//字段和数组元素会自动初始化为其类型的默认值。
int[] a = new int[3];
Console.WriteLine(a[1]); //0
//默认值
//所有类型的实例都有默认值。
//预定义的默认值是按位取0的内存表示的值。
//default关键字可用于获得任意类型的默认值。
decimal b=default (decimal);
Console.WriteLine(b); //0
//参数
//使用ref和out修饰符可以控制参数的传递方式
//按值传递参数(默认情况)
int c = 8;
Foo1(c); //传入的是c的副本
Console.WriteLine(c); //c仍等于8
StringBuilder d = new StringBuilder();
Foo2(d); //传入的是引用d的副本,Foo2方法将传入的参数赋值为null,并不会把d也赋值为null
Console.WriteLine(d.ToString()); //test
//ref修饰符
//按引用传递参数
int e = 8;
Foo3(ref e);
Console.WriteLine(e); //9
string f = "apple";
string g = "banana";
Swap(ref f, ref g);
Console.WriteLine(f); //banana
Console.WriteLine(g); //apple
//out修饰符
//与ref参数一样,out参数按引用传递
string h, i;
Split("abc def ghi",out h,out i);
Console.WriteLine(h); //abc def
Console.WriteLine(i); //ghi
//从C# 7开始,允许在调用含有out参数的方法时直接声明变量
Split("abc def ghi", out string j, out string k);
Console.WriteLine(j);
Console.WriteLine(k);
//使用out参数的方法时,可使用下划线来丢弃那些不感兴趣的参数
Split("abc def ghi",out string l, out _); //丢弃第二个out参数
//params修饰符
//params参数修饰符只能修饰方法中的最后一个参数,它能够使方法接受任意数量的指定类型参数。
//参数类型必须声明为数组
int total = Sum(1, 2, 3, 4);
Console.WriteLine(total); //10
//也可将普通的数组提供给params参数
int total2 = Sum(new int[] { 1, 2, 3, 4 });
Console.WriteLine(total2); //10
//可选参数
Foo4(); //20
//命名参数
Foo5(x: 1, y: 2); //1,2
//也可以写作
Foo5(y: 2, x: 1); //1,2
//var隐式类型局部变量
//如果编译器能够从初始化表达式中推断出变量的类型,就能够使用var关键字来代替类型声明
var m= "hello"; //string
var n= 8; //int
}
static void Foo1(int p)
{
p = p + 1;
Console.WriteLine(p);
}
static void Foo2(StringBuilder p)
{
p.Append("test");
p = null;
}
static void Foo3(ref int p)
{
p = p + 1;
Console.WriteLine(p);
}
static void Swap(ref string a,ref string b)
{
string temp = a;
a = b;
b = temp;
}
static void Split(string name,out string firstName,out string lastName)
{
int i = name.LastIndexOf(' ');
firstName = name.Substring(0,i);
lastName=name.Substring(i+1);
}
static int Sum(params int[] ints)
{
int sum = 0;
for (int i = 0; i < ints.Length; i++)
sum += ints[i];
return sum;
}
static void Foo4(int x = 20)
{
Console.WriteLine(x);
}
static void Foo5(int x,int y)
{
Console.WriteLine(x + "," + y);
}
C# 变量和参数
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。
推荐阅读更多精彩内容
- 传值参数 1、值参数创建变量副本2、对值参数的操作永远不影响变量的值 传值参数——值类型 传值参数——引用类型:创...
- 大家可能在编码中或多或少的使用过out的ref,但是是否注意过他两的详细用法以及区别? 本文想介绍下详细介绍下ou...
- 1.基本概念 堆(Heap)程序可以动态申请的存储空间,通过malloc系列函数分配,全局可访问。 栈(Stack...
- c#函数参数有四种类型,分别是:值参数、引用参数、输出参数、参数数组 在了解函数的参数之前,我们先来了解什么是实参...