C# ----- 数据类型(params/ref/out)

 这篇是各种数据类型,各种参数总结。有点乱。没来得及整理。有空会再整理下。还有这是搜集的各路资料和自己的一些总结。谢谢各路大神!!
1.理论概念
 
C#数据类型结构图:

计算机分为5个区

1.常量区
2.静态区 (static修饰的)
3.代码区  运行方法的时候会找到代码区
4.栈区(值类型,定义一个变量入栈开辟空间,定义完自动释放空间)int a = 10,此处a为值
5.堆区(数组中,new称为运算符,new的时候在堆中开辟空间)int[] a = new int[];此处a为存储的地址
 
拷贝
值类型是先copy相同的数值,再赋值给新的变量
引用类型是把存储的地址赋值给新的变量(数组)
 
 
2.示例
(1)值类型转换引用类型   
  class MainClass
     {
          public void Jiaohuan(int x,int y)
          {
               x=x+y;
               y=x-y;
               x=x-y;
          }
      MainClass mainclass = new MainClass();
      int a = 12;
      int b = 35;
      mainclass.Jiaohuan(a,b);
      Console.WriteLine ("a={0},b={1}",a,b);//然而实参没有交换
      int c =30;
      int d = c;
      d = 40;
      Console.WriteLine ("c={0},d={1}",c,d);

 

输出不改变
     
若想改变则在方法里面形参前加ref,输出处实参前也加ref;(ref意为把值类型转换为引用类型)
 //形参的值发生改变后,实参的值也会发生改变 
如下:
   
 class MainClass
     {
          public void Jiaohuan( ref int x,ref int y)//ref只适用于值类型,相当于把值类型转化为引用类型
          {
               x=x+y;
               y=x-y;
               x=x-y;
          }
          public static void Main (string[] args)
          {
               MainClass mainclass = new MainClass();
               int a = 12;
               int b = 35;
               mainclass.Jiaohuan(ref a,ref b);
               Console.WriteLine ("a={0},b={1}",a,b); //形参的值发生改变后,实参的值也会发生改变      

 

(2)数组是引用类型,则输出会改变
       
   public void Maopao(int[]a)
          {
               for(int i = 0;i<a.Length-1;i++){
                    for(int j =0;j<a.Length-i-1;j++){
                         if(a[j]>a[j+1])
                         {
                              int temp = a[j+1];
                         a[j+1] = a[j];
                         a[j] = temp;
                         }
                    }
               }
  int[] s = {1,5,6,7,2,4,3};
  int[] h = s;
  h[1] = 10;
  Console.WriteLine (s[1]);
  mainclass.Maopao(s);

 

输出改变
 
~!!注意:类里的字段存放在堆区(即使字段中用的变量是值类型)
 
3.装箱,拆箱
   装箱:把值类型的数据转换成引用类型的数据的过程
         int  num = 23;
         object obj = num;
         Console.WriteLine (obj);
   拆箱:把引用类型的数据转换成值类型的数据称为拆箱
         int count = (int)obj;
         Console.WriteLine (count); 
示例:
 ①params表示可变数组,即不确定数组的长短情况下声明。且params关键字后不允许有其他参数。
          public void PrintArr( params int[] a)//可变数组参数params
          {
               foreach(int n in a)
               {
                    Console.Write (n+" ");
               }
          }
//输出数组 int[] sh = {12,54,45,32,45}; mainclass.PrintArr(sh); Console.WriteLine (); mainclass.PrintArr(2,5,7,8,4,9);//使用params后可省去定义数组 Console.WriteLine (); mainclass.PrintArr();
②若params与其他值类型同时存在,则默认值类型后为可变数组
          public void PrintArr(int a,int b,params int[] jk)//可变数组参数params与别的值类型同存在
          {
               foreach(int y in jk)
               {
                    Console.Write (y+" ");
               }
          }
          mainclass.PrintArr(2,5,7,8,4,9);//使用params后可省去定义数组
输出结果:7 8 4 9
 
 
C# 参考之方法参数关键字:params、ref及out
如果在为方法声明参数时未使用 ref 或 out,则该参数可以具有关联的值。
可以在方法中更改该值,但当控制传递回调用过程时,不会保留更改的值。
通过使用方法参数关键字,可以更改这种行为。
 
4.ref
上面在值类型和引用类型的示例介绍中有提到了ref的用法。
ref 关键字使参数按引用传递。
其效果是,当控制权传递回调用方法时,在方法中对参数所做的任何更改都将反映在该变量中。
 
若要使用 ref 参数,则方法定义和调用方法都必须显式使用 ref 关键字。
传递到 ref 参数的参数必须最先初始化。这与 out 不同,out 的参数在传递之前不需要显式初始化。
属性不是变量,因此不能作为 ref 参数传递。
尽管 ref 和 out 在运行时的处理方式不同,但它们在编译时的处理方式是相同的。因此,如果一个方法采用 ref 参数,而另一个方法采用 out 参数,则无法重载这两个方法。例如,从编译的角度来看,以下代码中的两个方法是完全相同的。如果尝试这么做,将导致不能编译该代码。
如果一个方法采用 ref 或 out 参数,而另一个方法不采用这两类参数,则可以进行重载。
 
示例:
// keywords_ref.cs
 
using System;
 
class App
{
    public static void UseRef(ref int i)
    {
        i += 100;
        Console.WriteLine("i = {0}", i);
    }
 
    static void Main()
    {
        int i = 10;
 
        // 查看调用方法之前的值
        Console.WriteLine("Before the method calling: i = {0}", i);
 
        UseRef(ref i);
 
        // 查看调用方法之后的值
        Console.WriteLine("After the method calling: i = {0}", i);
        Console.Read();
    }
}
 
控制台输出:
Before the method calling : i = 10
i = 110
After the method calling: i = 110
5.out
out 关键字会导致参数通过引用来传递。这与 ref 关键字类似。
与 ref 的不同之处:
ref 要求变量必须在传递之前进行初始化。
尽管作为 out 参数传递的变量不需要在传递之前进行初始化,但需要调用方法以便在方法返回之前赋值。
    //买烟的方法  +out
        public int Maiyan(int money,out int change)//把零钱输出来,有out的话是把形参赋值给实参
        {
             int num = money/20;
             change = money%20;
              return num;
         }
 
               //输出参数,当返回值为两个,则在方法定义参数处加out,
               int lingqian;
               int number = mainclass.Maiyan(50,out lingqian);//拿了多少钱
               Console.WriteLine (number);
               Console.WriteLine (lingqian);
与 ref 示例不同的地方只要将 ref 改为 out,然后变量 i 仅需要声明即可。
static void Main()
{
    //int i = 10; 改为
    int i;
    //
}
6.参数 params
params 关键字可以指定在参数数目可变处采用参数的方法参数。
在方法声明中的 params 关键字之后不允许任何其他参数,并且在方法声明中只允许一个 params 关键字。
 
数组参数总结params

1.参数的长度可变。长度可以为0。

2.只能使用一次,而且要放到最后。

3.后跟数组类型,不能跟ref、out一起搭配使用
 
C#中方法的参数有4中类型:
值参数:不附加任何修饰符。
输出参数:以out修饰符声明,可返回一 个或多个值给调用者。
引用参数:以ref修饰符声明。
数组参数:以params修饰符声明。
 
示例:
// keywords_params.cs
 
using System;
 
class App
{
    public static void UseParams(params object[] list)
    {
        for (int i = 0; i < list.Length; i++)
        {
            Console.WriteLine(list[i]);
        }
    }
 
    static void Main()
    {
        // 一般做法是先构造一个对象数组,然后将此数组作为方法的参数
        object[] arr = new object[3] { 100, 'a', "keywords" };
        UseParams(arr);
 
        // 而使用了params修饰方法参数后,我们可以直接使用一组对象作为参数
        // 当然这组参数需要符合调用的方法对参数的要求
        UseParams(100, 'a', "keywords");
 
        Console.Read();
    }
}
 
 
 
 
posted @ 2015-12-08 16:17  王赛  阅读(430)  评论(0编辑  收藏  举报