由String类型分析,所产生的对参数传递之惑的解答

String 类型分析概要:

     String 是C#语言中用处最广的一种类型。然而其惯有的使用方法(ex,+、=、== etc.),很容易给人的错觉就是:它和其它值类型(ValueType,ex,int,float,double etc.)是一样的!然而由我的——《JavaScript浅析1——类型》中对JS中的String类型做了一定分析。然而在C#环境下,String又是以何种类型方式(值类型,引用类型?)存在的呢?先看一演示代码:

//Description:通过简单代码测试,验证String类型

//CopyRight:http://www.cnblogs.com/yangmingming

//Notes:环境是一个初始值为空的Label—lbelDisplayStringType;
          
// 一个显示String类型的TextBox—txtStringType,初始空;
          
// 一个提交按钮(附事件)btnSubmit;

public partial class TypeTest : System.Web.UI.Page
{
    
protected void Page_Load(object sender, EventArgs e)
    {

    }
    
    
protected void btnSubmit_Click(object sender, EventArgs e)
    {
        
string strTestType = "This is test string";
        lbelDisplayStringType.Text 
= "Display the Type of String";
        
if (!strTestType.GetType().IsValueType)
            txtStringType.Text 
= "String is Reference Type";
        
else
            txtStringType.Text 
= "String is ValueType";
    }

在测试过程中,我们看到的初始界面和按钮触发后界面对比图,如下示:

 

    可见在TextBox中显示的是:String 是引用类型!可它为什么这么像值类型呢?

    事实上,由于String 类型是如此特殊,以至于C#语言对其进行了"格外关照",因为它很大程度上不同于其余的对象-引用类型,所以C#对其进行了包装处理,使其具有了很多类似于值类型的特性(由以前学习的C++中对String对象方法的重载可见一斑!) ,而其本质是引用类型的。由此我们可以利用String这一特殊对象,延伸至我们下一话题——参数传递之惑的解答

 

参数传递之惑的解答:

      受Anytao的《你必须知道的.NET》之参数传递的艺术 影响,我想对参数传递的方法做一总结,以巩固所学,也对这一"绕人"问题做一厘清。 参数传递分为按值传递按引用传递(C#中提供按引用传递的Ref),下面就分别就其具有的两种类型——值类型引用类型,分而讨论之:


一:参数按值传递

    借助于函数的参数传递方式,以及上述讨论的String类型分析,我们选取int型值类型和String型引用类型,考察其在参数按值传递过程中的不同表现,分析原因。

后台代码如下:

//Description:通过代码测试,验证值类型和引用类型,在值传递过程中的不同表现

//CopyRight:http://www.cnblogs.com/yangmingming

//Notes:环境是初始值为空的四个TextBox,前面的Lbel标签标示其作用
          
//按钮标示调用函数,并通过TextBox值显示对比效果

public partial class ParaDelivery : System.Web.UI.Page
{
    
protected void Page_Load(object sender, EventArgs e)
    {

    }
    
protected void btnSubmit_Click(object sender, EventArgs e)
    {
        
int i = 1;
        
string str = "This is a String";
        txtItiValue.Text 
= i.ToString();
        txtRefValue.Text 
= str;

        AddValueType(i);
        AddRefType(str);
        txtChangedIntValue.Text 
= i.ToString();
        txtChangedRefValue.Text 
= str;
    }

    
//两个被调用函数
    private void AddValueType(int funi)
    {
        funi
=2;
    }
    
private void AddRefType(string funStr)
    {
        funStr 
="This is a changed String";
    }
}

而在按钮触发之后,我们来看一下其显示的对比效果:

 

 可见我们的调用函数中,企图对值类型变量i,和引用类型变量str重新赋值的目的都没有达到!

分析:

1.对于值类型的按值传递,其结果没有改变,这一点相信没有问题,因为它只是原变量的一种拷贝,并不会影响原值;

2.对于引用类型的按值传递,很多人会想当然的认为,这样的重赋值会改变原有的String变量值,但结果证明一切,它没有改变!因为虽然是对引用类型的按值传递,但是就其本质该引用(例中为str变量的引用),通过值类型传递过去的依然是它的拷贝——引用的拷贝。当对拷贝重赋值时,改变的只是拷贝引用变量的值(新的String对象地址),并不影响原String对象以及其对应引用。这样才出现了String对象未曾改变的结果。

 

二:参数按引用传递

    采用完全类似于上述的展现方式,我们揭示值类型和引用类型在按引用传递时的表现会是怎么样?先看后台代码:

//Description:通过代码测试,验证值类型和引用类型,在值传递过程中的不同表现

//CopyRight:http://www.cnblogs.com/yangmingming

//Notes:环境是初始值为空的四个TextBox,前面的Lbel标签标示其作用
          
//按钮标示调用函数,并通过TextBox值显示对比效果

public partial class ParaDelivery : System.Web.UI.Page
{
    
protected void Page_Load(object sender, EventArgs e)
    {

    }
    
protected void btnSubmit_Click(object sender, EventArgs e)
    {
        
int i = 1;
        
string str = "This is a String";
        txtItiValue.Text 
= i.ToString();
        txtRefValue.Text 
= str;

        AddValueType(
ref  i);
        AddRefType(
ref  str);
        txtChangedIntValue.Text 
= i.ToString();
        txtChangedRefValue.Text 
= str;
    }

    
//两个被调用函数
    private void AddValueType(ref  int funi)
    {
        funi
=2;
    }
    
private void AddRefType(ref  string funStr)
    {
        funStr 
="This is a changed String";
    }
}

可见我们为其加上了引用传递方式,在按钮触发之后,我们看到显示结果为:

 

可见通过引用传递调用函数,我们实现了对无论是值类型,还是引用类型的改变 ,下面分析其原因:

分析:

 

1.对于值类型的按引用传递,其结果得到改变,这是因为当按引用传递时,传递的是参数的地址,而在函数体内改变变量时,实现的是对该地址指向变量的操作(完全类似于C中对指针指向变量的重赋值,ex,*p=3);

2.对于引用类型的 按引用传递。既然按引用传递时,系统会自动传递该参数的地址,在这里也就是String对象的引用的地址(完全类似于C中的指针的指针的概念,ex,**p=3),这样在函数体内对变量改变时,实质上改变了对象本身,从而实现了对其的有效更改。

 

综述之,对值类型和引用类型,在按值传递和按引用传递过程中,存在着极大地相似性,我想这些是按值传递和按引用传递本质上要求的,不同的只是因为值类型和引用类型两种类型不同而已,然而其表现形式确实完全相同的。(自我感觉分析的不是很清楚,结合托管堆图就更好了,呵呵


 

 

 

 

 

posted @ 2010-01-30 15:05  Youngman  阅读(1067)  评论(1编辑  收藏  举报