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));
        }

    }

}

那么那道题目是否有答案呢?

猜你喜欢

转载自blog.csdn.net/qq_38261174/article/details/85334112