using System;
class Element
{
public int Number=10;
}
class Test
{
static void Change(Element s)
{
s.Number=100;
}
static void Main()
{
Element e=new Element();
Console.WriteLine(e.Number);
Change(e);
Console.WriteLine(e.Number);
}
}
程序经编译后执行输出:
10
100
我们看到即使传值方式仍然改变了类型为Element类的对象t。但严格意义上讲,我们是改变了对象t的域,而非对象t本身。我们再看下面的例子:
using System;
class Element
{
public int Number=10;
}
class Test
{
static void Change(Element s)
{
Element r=new Element();
r.Number=100;
s=r;
}
static void Main()
{
Element e=new Element();
Console.WriteLine(e.Number);
Change(e);
Console.WriteLine(e.Number);
}
}
程序经编译后执行输出:
10
10
传值方式根本没有改变类型为Element类的对象t!实际上,如果我们能够理解类这一C#中的引用类型(reference type)的特性,我们便能看出上面两个例子差别!在传值过程中,引用类型本身不会改变(t不会改变),但引用类型内含的域却会改变(t.Number改 变了)!C#语言的引用类型有:object类型(包括系统内建的class类型和用户自建的class类型--继承自object类型),string 类型,interface类型,array类型,delegate类型。它们在传值调用中都有上面两个例子展示的特性。
在传值和传址情况下,C#强制要求参数在传入之前由用户明确初始化,否则编译器报错!但我们如果有一个并不依赖于参数初值的函数,我们只是需要函数返回 时得到它的值是该怎么办呢?往往在我们的函数返回值不至一个时我们特别需要这种技巧。答案是用out修饰的输出参数。但需要记住输出参数与通常的函数返回 值有一定的区别:函数返回值往往存在堆栈里,在返回时弹出;而输出参数需要用户预先制定存储位置,也就是用户需要提前声明变量--当然也可以初始化。看下 面的例子:
using System;
class Test
{
static void ResoluteName(string fullname,out string firstname,out string lastname)
{
string[] strArray=fullname.Split(new char[]{' '});
firstname=strArray[0];
lastname=strArray[1];
}
public static void Main()
{
string MyName="Cornfield Lee";
string MyFirstName,MyLastName;
ResoluteName(MyName,out MyFirstName,out MyLastName);
Console.WriteLine("My first name: {0}, My last name: {1}",
MyFirstName, MyLastName);
}
}
程序经编译后执行输出:
My first name: Cornfield, My last name: Lee
在函数体内所有输出参数必须被赋值,否则编译器报错!out修饰符同样应该应用在函数声明和调用两个地方,除了充当返回值这一特殊的功能外,out修 饰符ref修饰符有很相似的地方:传址。我们可以看出C#完全摈弃了传统C/C++语言赋予程序员莫大的自由度,毕竟C#是用来开发高效的下一代网络平 台,安全性--包括系统安全(系统结构的设计)和工程安全(避免程序员经常犯的错误)是它设计时的重要考虑,当然我们看到C#并没有因为安全性而丧失多少 语言的性能,这正是C#的卓越之处,“Sharp”之处!
数组参数也是我们经常用到的一个地方--传递大量的数组集合参数。我们先看下面的例子:
using System;
class Test
{
static int Sum(params int[] args)
{
int s=0;
foreach(int n in args)
{
s+=n;
}
return s;
}
static void Main()
{
int[] var=new int[]{1,2,3,4,5};
Console.WriteLine("The Sum:"+Sum(var));
Console.WriteLine("The Sum:"+Sum(10,20,30,40,50));
}
}
程序经编译后执行输出:
The Sum:15
The Sum:150
可以看出,数组参数可以是数组如:var,也可以是能够隐式转化为数组的参数如:10,20,30,40,50。这为我们的程序提供了很高的扩展性。
class Element
{
public int Number=10;
}
class Test
{
static void Change(Element s)
{
s.Number=100;
}
static void Main()
{
Element e=new Element();
Console.WriteLine(e.Number);
Change(e);
Console.WriteLine(e.Number);
}
}
程序经编译后执行输出:
10
100
我们看到即使传值方式仍然改变了类型为Element类的对象t。但严格意义上讲,我们是改变了对象t的域,而非对象t本身。我们再看下面的例子:
using System;
class Element
{
public int Number=10;
}
class Test
{
static void Change(Element s)
{
Element r=new Element();
r.Number=100;
s=r;
}
static void Main()
{
Element e=new Element();
Console.WriteLine(e.Number);
Change(e);
Console.WriteLine(e.Number);
}
}
程序经编译后执行输出:
10
10
传值方式根本没有改变类型为Element类的对象t!实际上,如果我们能够理解类这一C#中的引用类型(reference type)的特性,我们便能看出上面两个例子差别!在传值过程中,引用类型本身不会改变(t不会改变),但引用类型内含的域却会改变(t.Number改 变了)!C#语言的引用类型有:object类型(包括系统内建的class类型和用户自建的class类型--继承自object类型),string 类型,interface类型,array类型,delegate类型。它们在传值调用中都有上面两个例子展示的特性。
在传值和传址情况下,C#强制要求参数在传入之前由用户明确初始化,否则编译器报错!但我们如果有一个并不依赖于参数初值的函数,我们只是需要函数返回 时得到它的值是该怎么办呢?往往在我们的函数返回值不至一个时我们特别需要这种技巧。答案是用out修饰的输出参数。但需要记住输出参数与通常的函数返回 值有一定的区别:函数返回值往往存在堆栈里,在返回时弹出;而输出参数需要用户预先制定存储位置,也就是用户需要提前声明变量--当然也可以初始化。看下 面的例子:
using System;
class Test
{
static void ResoluteName(string fullname,out string firstname,out string lastname)
{
string[] strArray=fullname.Split(new char[]{' '});
firstname=strArray[0];
lastname=strArray[1];
}
public static void Main()
{
string MyName="Cornfield Lee";
string MyFirstName,MyLastName;
ResoluteName(MyName,out MyFirstName,out MyLastName);
Console.WriteLine("My first name: {0}, My last name: {1}",
MyFirstName, MyLastName);
}
}
程序经编译后执行输出:
My first name: Cornfield, My last name: Lee
在函数体内所有输出参数必须被赋值,否则编译器报错!out修饰符同样应该应用在函数声明和调用两个地方,除了充当返回值这一特殊的功能外,out修 饰符ref修饰符有很相似的地方:传址。我们可以看出C#完全摈弃了传统C/C++语言赋予程序员莫大的自由度,毕竟C#是用来开发高效的下一代网络平 台,安全性--包括系统安全(系统结构的设计)和工程安全(避免程序员经常犯的错误)是它设计时的重要考虑,当然我们看到C#并没有因为安全性而丧失多少 语言的性能,这正是C#的卓越之处,“Sharp”之处!
数组参数也是我们经常用到的一个地方--传递大量的数组集合参数。我们先看下面的例子:
using System;
class Test
{
static int Sum(params int[] args)
{
int s=0;
foreach(int n in args)
{
s+=n;
}
return s;
}
static void Main()
{
int[] var=new int[]{1,2,3,4,5};
Console.WriteLine("The Sum:"+Sum(var));
Console.WriteLine("The Sum:"+Sum(10,20,30,40,50));
}
}
程序经编译后执行输出:
The Sum:15
The Sum:150
可以看出,数组参数可以是数组如:var,也可以是能够隐式转化为数组的参数如:10,20,30,40,50。这为我们的程序提供了很高的扩展性。