using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace _3._2
{
class Person
{
public string fullName;
public int age;
public Person(string n, int a)
{
fullName = n;
age = a;
}
public void PrintInfo()
{
Console.WriteLine(“{0}的年齡是{1}歲”, fullName, age);
}
}
class Program
{
public static void ArrayOfObjects(params Object [] list)
{
for(int i = 0; i < list.Length; i++)
{
if(list[i] is Person)
{
((Person)list[i]).PrintInfo();//此處要注意要注意一個細節就是(Person)list[i]外面一定要加括號,否則系統將檢測不到強制類型與數組是一體,將會報錯
}
else
{
Console.WriteLine(list[i]);
}
}
}
public static void SendAPersonByValue(Person p)
{//此處是值類型的傳遞,重點之地也在這個地方,
p.age = 99;//觀察可以發現這個是直接由形參獲取person類的成員變量進行賦值的
p = new Person("張三", 999);//此處則是利用構造函數初始化的過程,由此種形式執行的結果如最下面的圖所示
}
public static void SendAPersonByReference(ref Person p)
{
p.age = 555;
p = new Person("張三", 999);
}
static void Main(string[] args)
{
Console.WriteLine("*****爲person設置一個新的引用類型*****");
Person fred = new Person("李四", 12);
Console.WriteLine("值被覆蓋前的person對象是:");
fred.PrintInfo();
SendAPersonByValue(fred);
Console.WriteLine("值被覆蓋前的person對象是:");
fred.PrintInfo();//年齡的更改會有效果
Console.WriteLine("\n****通過person對象參考");
Person mel = new Person("小五",23);
Console.WriteLine("值被覆蓋前的person對象是:");
mel.PrintInfo();
SendAPersonByReference(ref mel);//注意此處實參也要加ref
Console.WriteLine("值被覆蓋前的person對象是:");
mel.PrintInfo();
Console.Read();
}
}
}
以上程序執行的結果是:
觀察執行結果可以發現p.age=99這條語句起到效果了,但是p=new person(“張三”,999)這條語句並沒有起到效果。其原因是這樣的:
根據一條總結的結論‘當將一個值類型的變量賦給另一個值類型的變量時,他們進行的是一個字段的複製,而將一個引用類型的變量賦給另一個引用類型的變量時,只會複製內存地址’。如此再來看這個例子,從上可以看出SendAPersonByValue(Person p)這個函數就是一個形參是個引用類型的參數,那麼調用這個函數時,實參與形參之間進行的傳遞關係就是p=fred這樣的引用傳遞關係,所以說它傳遞的應該是地址,p.age=99語句纔會影響原來的對象。但是再來看p=new person()這就是一個對象的初始化過程,初始化就意味着這是一個新的對象,不再是指向原對象的一個引用,所以它的執行結果不會影響原對象的結果。按照這樣的說法,我們只要將 p.age = 99;p = new Person(“張三”, 999);這兩條語句的順序調換一下,那麼p.age = 99語句也將不對原對象起效果。
下面是我將這兩條語句調換位置之後的執行結果,剛好驗證了我上述的推理: