类型参数与加入ref、out关键字的类型参数的区别

 先看例子:

    class TestZhiYin
    {
        static void Main(string[] args)
        {
            int i = 100;
            args ar=new args();
            string str = "One";//特殊的引用类型
            ChangeValueyin(ref i);
            ChangeValueyin(ref ar);
            ChangeStingyin( ref str);
            Console.WriteLine(i);//200
            Console.WriteLine(ar.j);//600
            Console.WriteLine(str);//Two
//            ChangeValuezhi(i);
//            ChangeValuezhi(ar);
//            ChangeStringzhi(str);
//            Console.WriteLine(i);//100
//            Console.WriteLine(ar.j);//600
//            Console.WriteLine(str);//One
        }

        static void ChangeValueyin(ref int iVlaue)
        {
            iVlaue = 200;
            Console.WriteLine(iVlaue);
        }
        static void ChangeValuezhi(int iVlaue)
        {
            iVlaue = 300;
            Console.WriteLine(iVlaue);
        }
        static void ChangeValueyin(ref args ar)
        {
         ar.j=600;
         Console.WriteLine(ar.j);
        }
        static void ChangeValuezhi(args ar)
        {
         ar.j=600;
         Console.WriteLine(ar.j);
        }
        static void ChangeStingyin( ref string sValue)
        {
            sValue = "Two";
            Console.WriteLine(sValue);
        }
        static void ChangeStringzhi(string sValue)
        {
            sValue = "Two";
            Console.WriteLine(sValue);
        }

    }


public class args
{
 public int j=5;
}

 

这里先说明一下:无论是值类型,还是引用类型不加ref、out关键字都是按值传递的。值类型传递的是值本身的拷贝,引用类型传递的是引用本身的拷贝。对值拷贝的操作不会影响到原来的值;对引用拷贝的操作(拷贝引用和原来引用指向同一个对象)可以影响原来的对象,但是特例string除外。

       加上ref、out就是按引用传递了(就是传递的真实内存地址),对于值类型来说就是值的内存地址,对于引用类型来说,就是这个引用的内存地址。这样的操作,都会改变函数外变的量。

 

下面进行结果分析:

第一次执行(按地址传参):

            int i = 100;
            args ar=new args();
            string str = "One";//特殊的引用类型
            ChangeValueyin(ref i);
            ChangeValueyin(ref ar);
            ChangeStingyin( ref str);
            Console.WriteLine(i);//200
            Console.WriteLine(ar.j);//600
            Console.WriteLine(str);//Two

其结果对比:

i=100-----执行函数后i=200

ar.j=5-----执行函数后ar.j=600

str="One"-----执行函数后str="Two"

无论是值类型,还是引用类型,按地址传递都将改变其原来值。

 

第二次执行(按值传参):

            ChangeValuezhi(i);
            ChangeValuezhi(ar);
            ChangeStringzhi(str);
            Console.WriteLine(i);//100
            Console.WriteLine(ar.j);//600
            Console.WriteLine(str);//One

其结果对比:

i=100-----执行函数后i=100

 

ar.j=5-----执行函数后ar.j=600

 

str="One"-----执行函数后str="One"

 

可以看出,当按值传参的时候,i与ar.j执行函数后结果是不一样的。

i没有被改变,因为传递的是i=100这个值的一个拷贝,对它的任何操作不会对原来的i=100有任何改变。

 

args类中j的值被改变了,因为args是引用类型,当按值(这个值就是args引用的一个拷贝)传递args时,

传递的是args引用的拷贝,引用拷贝和原来的引用都指向同一个对象,所以j被改变了。

 

再看str定义的是string类型,string也是引用类型,为什么没有像args一样?

string是特殊的引用类型,它具有恒定性,也就是说,一个字符串创建以后,不能再对它进行任何更改

对它更改都会重新创建一个新的字符串

比如:string str="avb"执行object.ReferenceEquals(str,str.ToUpper())将得到false

如果按一般引用类型,对原有引用上的修改不会引起重新创建一个新的对象。

如果对一个字符进行频繁的操作,这时你应该考虑用StringBuilder,StringBuilder维护的是一个字符串数组

对它的操作,会体现到它本身,而不是去创建另一个字符串对象,这样比对string的操作节省了内存空间

 

另外补充:

ref 参数传入前必须被初始化,out不用,out需要在过程中对它初始化

可以通过ref和out来实现方法重载,但又不允许通过区分ref和out来实现方法重载

比如上面可以实现ChangeValueyin ref或者out的重载

ChangeValueyin(int iVlaue)
ChangeValueyin(ref int iVlaue)

这样将不被允许

ChangeValueyin(out int iVlaue)
ChangeValueyin(ref int iVlaue)

 

 

仅代表个人观点,如果认识有什么不足还请指教!!!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值