C# List 作為參數傳遞的值變化


一、示例演示

namespace TestConsole
{
    class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine("");

            List<string> list1 = new List<string>();
            Test1(list1);
            Console.WriteLine(" list1:" + list1.Count()); // 總數量為 1

            Console.WriteLine("");
            Console.WriteLine("---- 亮瞎眼的分割線 ----"); 
            Console.WriteLine(""); 

            List<string> list2 = new List<string>();
            Test2(list2);
            Console.WriteLine(" list2:" + list2.Count()); // 總數量仍為 0

            Console.WriteLine("");
        }

        static void Test1(List<string> list)
        {
            list.Add("1");
            Console.WriteLine(" Test1():" + list.Count()); // 總數量為 1
        }

        static void Test2(List<string> list)
        {
            List<string> list2 = new List<string>();
            list2.Add("1");

            list = list2;
            Console.WriteLine(" Test2():" + list.Count()); // 總數量為 1
        }
    }

可以發現:

經過 Test1后,list 的元素數量由 0 變為 1 了,

經過 Test2后,list 的元素數量還是0。

二、解說

1.list類型是引用類型

2.引用本身是類似於一個“保存地址的值變量”
所以從方法外部傳入引用到方法里,那么其實引用本身是復制了一份副本來給方法里使用的,只是說這個復制的引用副本和之前的引用的內容(也就是所指向的對象內存地址)是一樣的,所以通過引用操作對象的數據時,可以看到2個引用都操作的同一個對象;但如果你是修改了引用副本本身的值內容(將該引用指向了一個新的對象的內存地址),那么是不會影響到之前方法外的那個引用的,所以修改后會發現2個引用所指向的對象不同了

而如果對象引用參數前加上了ref,那么方法參數所傳遞的不再是引用的副本,而是引用的地址了(即通過引用的地址找到引用,再讀出引用里保存的內存地址值,再根據則個地址值去找到真正要操作的對象),所以如果此時你再修改這個引用的值時,會根據引用的地址找到方法外的那個引用,然后修改其內容,所以會發現方法外的引用也會指向新的對象了

3這里有三段代碼

你可以看看,體會一下:

(1)

List<string> list=new List<string>();
ModifyList(list);
Console.WriteLine(list.Count)
 
private void ModifyList(List<string> list)
{
   // 這里的list其實已經是一個引用副本了,但是所指向的內存地址仍然是原本方法外面的對象的,所以后面用該引用的Add方法所操作的,仍然是原本方法外面的對象的內存數據
    list.Add("1");
    list.Add("2");
    list.Add("3");
}

(2)

List<string> list=new List<string>();
ModifyList(list);
Console.WriteLine(list.Count)
 
private void ModifyList(List<string> list)
{
    list = new List<string>(); // 這里其實已經將引用指向了新的內存地址,所以后續的Add操作是在操作新對象的內存數據,而原來方法外的對象其實是沒有受到影響的
    list.Add("1");
    list.Add("2");
    list.Add("3");
}

(3)

List<string> list=new List<string>();
List<string> copy = list; // 復制一個引用
ModifyList(ref list);
Console.WriteLine(copy.Count) // 復制的這個引用仍然指向原來最早的那個List
Console.WriteLine(list.Count) // list這個引用已經在ModifyList方法里被修改了,指向的是在ModifyList方法里新new出來的對象了
 
private void ModifyList(ref List<string> list)
{
    list = new List<string>(); // 因為有ref,所以這里其實已經將方法外原本的那個引用也指向了新的內存地址,所以后續的Add操作是在操作新對象的內存數據,並且方法外原本的那個引用也指向了這個新的對象
    list.Add("1");
    list.Add("2");
    list.Add("3");
}

 

 

參考:

http://www.cftea.com/c/2013/01/5724.asp

http://bbs.csdn.net/topics/390600826


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM