值传递和引用传递 (C# ,java )

来源:互联网 发布:现在学什么编程语言好 编辑:程序博客网 时间:2024/06/03 16:35
C#
    C# ,参数传递过程中,方法调用是,是值传递还是引用传递取决于参数类型(基本数据类型,引用数据类型),
function  A  ( int  t){
t=5;
}  当是值传递时,function 内部对参数的CRUD不会改变外部参数的值;
function A(List<Object>  T){
T[0].Name="javaandroidc";//   调用之前T[0].Name的Value为“rose”
};  但是引用传递时,function 内部对参数的CRUD会改变外部参数的值
ArrayList,HachTable,List<T>,Dictionary<K,Y>这些都是引用类型;
EG:
 public class ProvinceSampleService    {        SampleManagement sampleManagement = new SampleManagement();        public string CheckProvinceSample(RequestDetail infor)        {                     #region  // start  检查 样品 产地 身份是否一致            Sample SampleForChoice = new Sample();            ProductSource SampleForCheck = new ProductSource();            SampleForChoice = sampleManagement.GetSampleByID(infor.SampleID);            SampleForCheck = sampleManagement.GetSamplebySampleNameAndSamplePalceAndProvince(SampleForChoice.SampleName, SampleForChoice.SamplePlace, infor.ProvinceName);            string flag = string.Empty;            if (!string.IsNullOrEmpty(SampleForCheck.ProductId))            {                if (!SampleForCheck.ProductId.Equals(infor.SampleID))                {                    flag = ("您选择的样品应用省份为" + infor.ProvinceName + ",该省份产品" + SampleForChoice.SampleName + "只能选择产地为" + SampleForCheck.ProductSourceName + "的样品,系统已经自动为你更改,如果问题,重新选择省份或联系商务部供应链组!") + ":" + SampleForCheck.ProductId;                     infor.SampleID = SampleForCheck.ProductId;// 此处会改变外部变量  Infor的值                }                else                {                    flag = string.Empty;                }            }            else            {                flag = ("您选择的样品应用省份为" + infor.ProvinceName + ",产地为" + SampleForCheck.ProductSourceName + "的" + SampleForChoice.SampleName + "没有对应的样品,请您重新选择省份或联系商务部供应链组!") + ":" + string.Empty;            }            return flag;            #endregion  // end  检查 样品 产地 身份是否一致        }    }

调用时:
                protected void gvSample_RowUpdating(object sender, GridViewUpdateEventArgs e)        {   // 点击更新按钮后,点击保存按钮            int i = this.gvSample.EditIndex;            //获取文本框的值            string DetailID = ((HiddenField)(this.gvSample.Rows[i].FindControl("DetailID"))).Value.ToString();            string SampleID = this.hidEditSampleID.Value.ToString();            string OrignalApplicantInitial = this.hidEditOrignalApplicantInitial.Value.ToString();            RequestDetail infor = new RequestDetail();            infor = (from c in SampleDetails where c.SampleID == SampleID && c.OrignalApplicantInitial == OrignalApplicantInitial select c).FirstOrDefault();            if (infor != null)            {                //         SampleDetails.Remove(infor);                infor.RequestID = 0;                infor.OrignalApplicantInitial = (gvSample.Rows[e.RowIndex].FindControl("txtOrignalApplicantInitial_update") as TextBox).Text.Trim().ToString();                infor.SampleType = (gvSample.Rows[e.RowIndex].FindControl("HidSampleType_update") as HiddenField).Value.Trim().ToString();                infor.SampleID = (gvSample.Rows[e.RowIndex].FindControl("hidSampleID_update") as HiddenField).Value.Trim().ToString();                infor.SamplePrice = Convert.ToDecimal((gvSample.Rows[e.RowIndex].FindControl("hidSamplePrice_update") as HiddenField).Value.Trim().ToString());                infor.SampleName = (gvSample.Rows[e.RowIndex].FindControl("txtSampleName") as TextBox).Text.Trim().ToString();                infor.SampleForm = (gvSample.Rows[e.RowIndex].FindControl("HidSampleForm_update") as HiddenField).Value.Trim().ToString();                string sampleNumber = (gvSample.Rows[e.RowIndex].FindControl("txtSampleNumber_update") as TextBox).Text.Trim().ToString();                int OutsampleNumber = 0;                int.TryParse(sampleNumber, out OutsampleNumber);                infor.SampleNumber = OutsampleNumber;                //infor.ShippingAddress = (gvSample.Rows[e.RowIndex].FindControl("txtShippingAddress_update") as HiddenField).Value.Trim().ToString();                infor.DeliveryAddress = (gvSample.Rows[e.RowIndex].FindControl("txtDeliveryAddress_update") as TextBox).Text.Trim().ToString();                infor.CostCenter = (gvSample.Rows[e.RowIndex].FindControl("HidCostCenter_update") as HiddenField).Value.Trim().ToString();                infor.OrderNumber = (gvSample.Rows[e.RowIndex].FindControl("txtOrderNumber_update") as TextBox).Text.Trim().ToString();                infor.ProvinceID = (gvSample.Rows[e.RowIndex].FindControl("ddrProvince_update") as DropDownList).SelectedValue.Trim().ToString();                infor.ProvinceName = (gvSample.Rows[e.RowIndex].FindControl("ddrProvince_update") as DropDownList).SelectedItem.Text.Trim().ToString();                infor.DeliveryContact = (gvSample.Rows[e.RowIndex].FindControl("txtDeliveryContact_update") as TextBox).Text.Trim().ToString();                infor.DeliveryMobile = (gvSample.Rows[e.RowIndex].FindControl("txtDeliveryMobile_update") as TextBox).Text.Trim().ToString();                infor.SampleSumPrice = Convert.ToInt32(sampleNumber) * infor.SamplePrice;                #region 项目类 ,更新时联系人不能为空                var p = this.Parent;                string RequestProposeString = string.Empty;                DropDownList hidFlag = (DropDownList)p.FindControl("ddlRequestProposeDisplayBids");                if (hidFlag != null)                {                    RequestProposeString = hidFlag.SelectedItem.Text;                }                // 联系人不能为空---start                string ddlRequestProposeDisplayBidsQuery = "";                List<Ones_ConfigValues> ListConfigValues = config.GetModelList(new string[] { "Project" });                if (ListConfigValues.Count > 0)                {                    ddlRequestProposeDisplayBidsQuery = ListConfigValues[0].ConfigValue;                }                if (ddlRequestProposeDisplayBidsQuery.Equals(RequestProposeString.Trim()))                {                    if (String.IsNullOrEmpty(infor.DeliveryContact))                    {                        Alert("申请目的为项目类时,联系人不能为空");                        return;                    }                }                // 联系人不能为空---end                #endregion                #region  start  检查 样品 产地 省份是否一致                ProvinceSampleService provinceSampleService = new ProvinceSampleService();                string flag = provinceSampleService.CheckProvinceSample(infor);                    if (!string.IsNullOrEmpty(flag))                {                    string[] result = new string[2];                    result = flag.Split(':');                    string ReturnFlag = result[1].Trim();                    Alert(result[0]);                    if (!string.IsNullOrEmpty(ReturnFlag.Trim()))                    {                        infor.SampleID = ReturnFlag;                    }                    else                    {                        return;                    }                }                #endregion  检查 样品 产地 省份是否一致                // 项目类医生超限                               RequestDetailService requestDtailService = new RequestDetailService();                List<RequestDetail> ListRequestDetailPage = new List<RequestDetail>();                ListRequestDetailPage.Add(infor);                string DoctorCountListFlag = requestDtailService.CheckDoctorDrugCountLimit(RequestProposeString, ListRequestDetailPage);                if (!string.IsNullOrEmpty(DoctorCountListFlag))                {                    Alert(DoctorCountListFlag);                    return;                }                // end 项目类医生超限                SampleDetails.Remove(infor);                if (RequestBaseID > 0)                {                    infor.RequestID = RequestBaseID;                    string ID = DetailManagement.Add2(infor);                    if (!string.IsNullOrEmpty(ID))                    {                        DetailManagement.DeleteByRequestDetailID(DetailID);                    }                }                else                {                    infor.RequestID = -1;                    if (!string.IsNullOrEmpty(infor.SampleID) && !string.IsNullOrEmpty(infor.OrignalApplicantInitial))                    {                        SampleDetails.Add(infor);                    }                }            }            this.gvSample.ShowFooter = true;            this.gvSample.EditIndex = -1;            BindData();            getTotalSum();        }
C#值类型数据直接在他自身分配到的内存中存储数据,而C#引用类型只是包含指向存储数据位置的指针。
基础数据类型(string类型除外):包括整型、浮点型、十进制型、布尔型。整型包括:sbyte、byte、char、short、ushort、int、uint、long、ulong 这九种类型;浮点型就包括 float 和 double 两种类型;十进制型就decimal ;布尔型就是 bool 型了。结构类型:就是 struct 型。枚举类型:就是 enum 型。引用类型有五种:class、interface、delegate、object、string引用类型作为参数时:1、在修改变量本身时,结果类似于值传递,即不会改变传递前的变量的值2、在修改变量的属性或字段时,才是引用传递,会影响到传递前的变量的值3、参数使用了ref后,才是真正的引用传递,不管修改变量本身还是修改变量的属性或字段,都会影响到传递前的变量的值值传递:传的是对象的值拷贝。(即函数内参数对象是调用时传递的对象的栈中对象的拷贝。)引用传递:传的是栈中对象的地址。(即函数内参数对象与调用时传递的对象完全是同一栈中对象。)C#值类型数据直接在他自身分配到的内存中存储数据,而C#引用类型只是包含指向存储数据位置的指针。基础数据类型(string类型除外):包括整型、浮点型、十进制型、布尔型。整型包括:sbyte、byte、char、short、ushort、int、uint、long、ulong 这九种类型;浮点型就包括 float 和 double 两种类型;十进制型就decimal ;布尔型就是 bool 型了。结构类型:就是 struct 型。枚举类型:就是 enum 型。引用类型有五种:class、interface、delegate、object、string引用类型作为参数时:1、在修改变量本身时,结果类似于值传递,即不会改变传递前的变量的值2、在修改变量的属性或字段时,才是引用传递,会影响到传递前的变量的值3、参数使用了ref后,才是真正的引用传递,不管修改变量本身还是修改变量的属性或字段,都会影响到传递前的变量的值值传递:传的是对象的值拷贝。(即函数内参数对象是调用时传递的对象的栈中对象的拷贝。)引用传递:传的是栈中对象的地址。(即函数内参数对象与调用时传递的对象完全是同一栈中对象。)在Java中:1. 基本类型和基本类型变量被当作参数传递给方法时,是值传递。在方法实体中,无法给原变量重新赋值,也无法改变它的值。   2. 对象和引用型变量被当作参数传递给方法时,是引用传递。在方法实体中,无法给原变量重新赋值,但是可以改变它所指向对象的属性。和c#中的一样,只不过Java中没有ref, out等关键字C#值类型数据直接在他自身分配到的内存中存储数据,而C#引用类型只是包含指向存储数据位置的指针。基础数据类型(string类型除外):包括整型、浮点型、十进制型、布尔型。整型包括:sbyte、byte、char、short、ushort、int、uint、long、ulong 这九种类型;浮点型就包括 float 和 double 两种类型;十进制型就decimal ;布尔型就是 bool 型了。结构类型:就是 struct 型。枚举类型:就是 enum 型。引用类型有五种:class、interface、delegate、object、string引用类型作为参数时:1、在修改变量本身时,结果类似于值传递,即不会改变传递前的变量的值2、在修改变量的属性或字段时,才是引用传递,会影响到传递前的变量的值3、参数使用了ref后,才是真正的引用传递,不管修改变量本身还是修改变量的属性或字段,都会影响到传递前的变量的值值传递:传的是对象的值拷贝。(即函数内参数对象是调用时传递的对象的栈中对象的拷贝。)引用传递:传的是栈中对象的地址。(即函数内参数对象与调用时传递的对象完全是同一栈中对象。)*****************************************************************************************************************************************************************************************
解析:CLR支持两种类型:值类型和引用类型。用Jeffrey Richter(《CLR via C#》作者)的话来说,“不理解引用类型和值类型区别的程序员将会把代码引入诡异的陷阱和诸多性能问题”。这就要求我们正确理解和使用值类型和引用类型。值类型包括C#的基本类型(用关键字int、char、float等来声明),结构(用struct关键字声明的类型),枚举(用enum关键字声明的类型);而引用类型包括类(用class关键字声明的类型)和委托(用delegate关键字声明的特殊类)。C#中的每一种类型要么是值类型,要么是引用类型。所以每个对象要么是值类型的实例,要么是引用类型的实例。值类型的实例通常是在线程栈上分配的(静态分配),但是在某些情形下可以存储在堆中。引用类型的对象总是在进程堆中分配(动态分配)。(1)在C#中,变量是值还是引用仅取决于其基本数据类型。C#的基本数据类型都与平台无关。C#的预定义类型并没有内置于语言中,而是内置于.NET Framework中。.NET使用通用类型系统(CTS)定义可以在中间语言(IL)中使用的预定义数据类型。C#中所有的数据类型都是对象。它们可以有方法、属性等。例如,在C#中声明一个int变量时,声明实际上是CTS(通用类型系统)中System.Int32的一个实例:
复制代码 代码如下:
int i;i = 1;string s;s = i.ToString();
 (2)System.Object和System.ValueType。引用类型和值类型都继承自System.Object类。不同的是,几乎所有的引用类型都直接从System.Object继承,而值类型则继承其子类,即直接继承System.ValueType。作为所有类型的基类,System.Object提供了一组方法,这些方法在所有类型中都能找到。其中包含toString方法及clone等方法。System.ValueType继承System.Object。它没有添加任何成员,但覆盖了所继承的一些方法,使其更适合于值类型。(3)值类型。C#的所有值类型均隐式派生自System.ValueType:结构体:struct(直接派生于System.ValueType)。数值类型:整型,sbyte(System.SByte的别名),short(System.Int16),int(System.Int32),long(System.Int64),byte(System.Byte),ushort(System.UInt16),uint(System.UInt32),ulong(System.UInt64),char(System.Char)。浮点型:float(System.Single),double(System.Double)。用于财务计算的高精度decimal型:decimal(System.Decimal)。 bool型:bool(System.Boolean的别名)。用户定义的结构体(派生于System.ValueType)。 枚举:enum(派生于System.Enum)。可空类型。 每种值类型均有一个隐式的默认构造函数来初始化该类型的默认值。例如:
复制代码 代码如下:
int i = 0;等价于:int i = new int();
使用new运算符时,将调用特定类型的默认构造函数并对变量赋予默认值。在上例中,默认构造函数将值0赋给了i。所有的值类型都是密封(seal)的,所以无法派生出新的值类型。值得注意的是,System.ValueType直接派生于System.Object。即System.ValueType本身是一个类类型,而不是值类型。其关键在于ValueType重写了Equals()方法,从而对值类型按照实例的值来比较,而不是引用地址来比较。可以用Type.IsValueType属性来判断一个类型是否为值类型:
复制代码 代码如下:
TestType testType = new TestType ();if (testTypetype.GetType().IsValueType){    Console.WriteLine("{0} is value type.", testType.ToString());}
(4)引用类型C#有以下一些引用类型:数组(派生于System.Array) 用户需定义以下类型。 类:class(派生于System.Object); 接口:interface(接口不是一个“东西”,所以不存在派生于何处的问题。接口只是表示一种contract约定[contract])。委托:delegate(派生于System.Delegate)。 object(System.Object的别名); 字符串:string(System.String的别名)。 可以看出:引用类型与值类型相同的是,结构体也可以实现接口;引用类型可以派生出新的类型,而值类型不能;引用类型可以包含null值,值类型不能;引用类型变量的赋值只复制对象的引用,而不复制对象本身。而将一个值类型变量赋给另一个值类型变量时,将复制包含的值。(5)内存分配。值类型的实例经常会存储在栈上的。但是也有特殊情况。如果某个类的实例有个值类型的字段,那么实际上该字段会和类实例保存在同一个地方,即堆中。不过引用类型的对象总是存储在堆中。如果一个结构的字段是引用类型,那么只有引用本身是和结构实例存储在一起的(在栈或堆上,视情况而定)。如下例所示:
复制代码 代码如下:
public struct ValueTypeStruct{    private object referenceTypeObject;    public void Method()    {        referenceTypeObject = new object();        object referenceTypeLocalVariable = new object();    }}ValueTypeStruct valueTypeStructInstance = new ValueTypeStruct();valueTypeStructInstance.Method();//referenceTypeObject 和 referenceTypeLocalVariable 都在哪存放?单看valueTypeStructInstance,这是一个结构体实例,感觉似乎是整块都在栈上。但是字段referenceTypeObject是引用类型,局部变量referenceTypeLocalVarible也是引用类型。public class ReferenceTypeClass{    private int _valueTypeField;    public ReferenceTypeClass()    {        _valueTypeField = 0;    }    public void Method()    {        int valueTypeLocalVariable = 0;    }}ReferenceTypeClass referenceTypeClassInstance = new ReferenceTypeClass();// _valueTypeField在哪存放?referenceTypeClassInstance.Method();// valueTypeLocalVariable在哪存放?
referenceTypeClassInstance也有同样的问题,referenceTypeClassInstance本身是引用类型,似乎应该整块部署在托管堆上。但字段_valueTypeField是值类型,局部变量valueTypeLocalVariable也是值类型,它们究竟是在栈上还是在托管堆上?对上面的情况正确的分析是:引用类型在栈中存储一个引用,其实际的存储位置位于托管堆。为了方便,简称引用类型部署在托管堆上。值类型总是分配在它声明的地方,作为字段时,跟随其所属的变量(实例)存储;作为局部变量时,存储在栈上。(6)辨明值类型和引用类型的使用场合。在C#中,我们用struct/class来声明一个类型为值类型/引用类型。考虑下面的例子:SomeType[] oneTypes = new SomeType[100];如果SomeType是值类型,则只需要一次分配,大小为SomeType的100倍。而如果SomeType是引用类型,刚开始需要100次分配,分配后数组的各元素值为null,然后再初始化100个元素,结果总共需要进行101次分配。这将消耗更多的时间,造成更多的内存碎片。所以,如果类型的职责主要是存储数据,值类型比较合适。一般来说,值类型(不支持多态)适合存储供 C#应用程序操作的数据,而引用类型(支持多态)应该用于定义应用程序的行为。通常我们创建的引用类型总是多于值类型。如果满足下面情况,那么我们就应该创建为值类型:该类型的主要职责用于数据存储。 该类型的共有接口完全由一些数据成员存取属性定义。 该类型永远不可能有子类。 该类型不具有多态行为。答案:在C#中,变量是值还是引用仅取决于其数据类型。C#的值类型包括:结构体(数值类型、bool型、用户定义的结构体),枚举,可空类型。C#的引用类型包括:数组,用户定义的类、接口、委托,object,字符串。数组的元素,不管是引用类型还是值类型,都存储在托管堆上。引用类型在栈中存储一个引用,其实际的存储位置位于托管堆。简称引用类型部署在托管推上。值类型总是分配在它声明的地方:作为字段时,跟随其所属的变量(实例)存储;作为局部变量时,存储在栈上。值类型在内存管理方面具有更好的效率,并且不支持多态,适合用做存储数据的载体;引用类型支持多态,适合用于定义应用程序的行为。**********************************************************************************************************************************************************************************在Java中:1. 基本类型和基本类型变量被当作参数传递给方法时,是值传递。在方法实体中,无法给原变量重新赋值,也无法改变它的值。2. 对象和引用型变量被当作参数传递给方法时,是引用传递。在方法实体中,无法给原变量重新赋值,但是可以改变它所指向对象的属性。和c#中的一样,只不过Java中没有ref, out等关键字1. 基本类型和基本类型变量被当作参数传递给方法时,是值传递。在方法实体中,无法给原变量重新赋值,也无法改变它的值。 2. 对象和引用型变量被当作参数传递给方法时,是引用传递。在方法实体中,无法给原变量重新赋值,但是可以改变它所指向对象的属性。
0 0
原创粉丝点击