1. 程式人生 > >C#:值型別和引用型別

C#:值型別和引用型別

之前有篇文章講到引數傳遞,https://blog.csdn.net/qq_38261174/article/details/84934444

但並未對值型別和引用型別做一個詳細的瞭解。

值型別和引用型別詳細的說明在右邊的網址中有:http://www.runoob.com/csharp/csharp-data-types.html

之前看了詳細說明,於是在我的腦海中就留下了一個印像,string是引用型別。對任何引用型別做了改變就會有影響。於是這句話在下面把我成功帶入坑。

 

今天早上看了一篇部落格,https://blog.csdn.net/luxin10/article/details/7178090

就講到了值型別和引用型別,我第一次看到題目我給出的答案也是錯的,看來還是被帶坑裡了。

題目是這樣的:

using System;
public class Test1
{
 public static void Main()
    {
        int num = 0;
        Person p = new Person("Li");
        A1(p, num);
        Console.WriteLine("{0},{1}", p.name, num);
    }
    static void A1(Person p, int num)
    {
        p = new Person("Wang");
        num = 1;
    }
}
public class Person
{
    public string name;
    public Person(string name)
    {
        this.name = name;
    }
}

說說上面的程式產生的結果,以及產生這個結果的原因是什麼?

我想著不是很簡單嗎,因為Person是引用型別,對引用型別做了改變肯定會有影響,而int是值型別,則沒有影響。所以我第一次給出的答案是 :   Wang   0

但是一執行,答案卻是   Li    0   ,這是為什麼呢?

 

我自己畫了上面這個圖,應該可以很好的理解了

 

但是我還看到了另一篇文章,我又有一個問題了,值型別真的不可以改變嗎?比如上面的 num在方法中做了改變,但最終輸出時卻毫無影響,這是值型別的特點。

那麼有一道題目是這樣的,如下:

public class Program {
        static void Main(string[] args) {

            int a = 4;
            int b = 5;

            Change(a,b); //自己按照要求完成這個方法

            //要求如下:
            Console.WriteLine("{0}  {1}",a,b); //列印結果要為:   400  500
            
            Console.ReadKey();
        }


        
    }

這不是很奇怪嗎?因為a,b是值型別,不管怎樣都是4和5啊,怎麼會打印出400和500呢

別跟我說a*100,b*100,作為一名程式設計師,那就真的有點說不過去了。

但是仔細想一想,有一種東西很奇特,那就是 反射,利用反射就可以做到。

之前有篇反射的使用文章可以瞭解下:https://blog.csdn.net/qq_38261174/article/details/84890229

很奇怪,我用c#語言試驗了一波,發現 反射居然也不能實現。希望知道的各位能給我答案。

我的程式碼如下:並沒有解決問題。

using System;
using System.Reflection;

namespace TestSuanfa {
    public class Program {
        static void Main(string[] args) {

            int a = 4;
            int b = 5;

            Change(a,b); //自己按照要求完成這個方法   (實引數中沒有 ref,有ref就簡單了)

            //要求如下:
            Console.WriteLine("{0}  {1}",a,b); //列印結果要為:   400  500
            
            Console.ReadKey();
        }

        //我的Change方法如下,形參是自己定的,你也可以定義其它引數,只要符合題目要求就行了
        public static void Change(int a, int b) {
            Type type = typeof(int);
            //值型別,預設屬性名  m_value  可通過 GetFields()打印出來得到
            FieldInfo f = type.GetField("m_value",BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static | BindingFlags.GetField);
            object boxa = a;
            object boxi = 100;
            f.SetValue(boxa,boxi);
            Console.WriteLine(f.GetValue(boxa));
        }

    }

}

列印如下,並沒有出現預料中的結果,希望解決的各位給我答案。

然後我用指標查看了a,b的地址,發現了原來是地址不一樣,所以無法解決。。

using System;
using System.Reflection;

namespace TestSuanfa {
    public class Program {
        static void Main(string[] args) {

            int a = 4;
            int b = 5;
            unsafe {
                Console.WriteLine("{0}  {1}", (int)&a, (int)&b);
            }

            Change(a,b); //自己按照要求完成這個方法   (引數中沒有 ref,有ref就簡單了)

            //要求如下:
            Console.WriteLine("{0}  {1}",a,b); //列印結果要為:   400  500
            
            Console.ReadKey();
        }

        //我的Change方法如下,引數是自己定的,你也可以定義其它引數,只要符合題目要求就行了
        public static unsafe void Change(int a, int b) {
            Console.WriteLine("{0}  {1}", (int)&a, (int)&b);
            Type type = typeof(int);
            //值型別,預設屬性名  m_value  可通過 GetFields()打印出來得到
            FieldInfo f = type.GetField("m_value",BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static | BindingFlags.GetField);
            object boxa = a;
            object boxi = 100;
            f.SetValue(boxa,boxi);
            Console.WriteLine(f.GetValue(boxa));
        }

    }

}

 

那麼那道題目是否有答案呢?