C#基础- 属性 方法参数 数据类型-09

昨晚刚刚躺下准备睡觉,我妈敲门说和我爸吵架了,过来跟我挤挤...几分钟之后我爸来让我出去一下,说是要给我妈道歉。我刚走出房门,就听见里边的锁门声...然后我爸说:你去我房里睡吧...过去之后我才知道,原来他们屋里的空调坏了......



========================手动分割线==========================

一、属性

  • 由于面向对象的封装特性,通常不会把字段设置成public,就需要我们手动添加为字段赋值的接口;
  • 为类中字段手写Get方法和Set方法是很麻烦,所以程序帮我们自动的封装出这个两个方法,也就是添加属性。

1.1 属性的添加

属性的出现的前提是存在私有字段。

1.1.1 添加一个私有字段

           private string name;

1.1.2 添加属性

      访问修饰符 属性类型 属性名{
            get{
                返回属性值
            }
            set {
                存储属性值
            }
        }
  • 访问修饰符:约束属性的可见度
  • 属性的类型和对应的字段的类型一致
  • 属性名与对应的字段名一致,但首字母大写,以便和字段做区分
  • get方法:对属性进行取值操作,访问器, 直接返回对应的字段中存储的值
  • set方法:对属性进行赋值操作,设置器, 取到隐藏参数value中存储的用户传入的参数,并存储到对应字段中
  • value:属性生成的方法,不需要参数,而是使用隐藏参数value取代,value中存储的就是用户传入的所要赋的值
  • 属性的优势:提高数据访问的安全性和灵活性。

1.2 番外-属性和字段的区别:

在C#中,我们可以非常自由的、毫无限制的访问公有字段,但在一些场合中,我们可能希望限制只能给字段赋于某个范围的值、或是要求字段只能读或只能写, 或是在改变字段时能改变对象的其他一些状态,这些单靠字段是无法做到的,于是就有了属性,属性中包含两个块:set和get,set块负责属性的写入工作,get块负责属性的读取工作。
在两个块中都可以做一些其他操作,如在set中验证赋的值是否符合要求并决定是否进行赋值。 当缺少其中一块时属性就只能读或只能写,set和get块中属性必需有一个,因为即不能读又不能写的属性是没有意义的。

在上节最后讲到setter和getter方法,那么现在我们来对比下它和属性的区别。

1.2.1 首先有一个私有字段:

   class Person
    {
        private string name;
    }  

1.2.2 手动添加为字段赋值setter和取值gettter的方法

   class Person
    {
        private string name;
        public void SetName(string _name) {
                name = _name;
        }

         public string GetName() {
              return name;
        }
    }  

1.2.3 添加属性

   class Person
    {
        private string name;

        public string Name {
            get {
                 // 取值方法,直接返回对应的字段中存储的值即可
                return name;
            }
            set {
                 // 赋值方法,取到隐藏参数value中存储的用户传入的参数,并存储到对应字段中
                name = value;
            }
    }  

1.2.4 在set方法中,可以灵活控制赋值条件

   class Person
    {
        private  string gender = "妖怪";
        public string Gender {
            get {
                return gender;
            } 
            set {
                if (value != "不详") {
                    return;
                }
                gender = value;
            }
        }
    }  

1.3 属性的使用

在类内部定义好了字段属性后,在Main函数内部调用:

    static void Main(string[] args)
    {
        Person p1 = new Person();
        // 使用属性
        p1.Name = "妹子";// 调用set方法,赋值操作
        Console.WriteLine(p1.Name);// 调用get方法,取值操作
        p1.Gender = "不详";
        Console.WriteLine(p1.Gender);
        p1.Age = 18;
        Console.WriteLine(p1.Age);
    }

二、数据类型

在C#中,所有的数据类型可划分为两种:

  • 值类型:在栈中分配空间,由系统自动分配。
  • 引用类型:在堆中分配空间,由程序员用“new”来分配空间

2.1 值类型与引用类型的不同

这两者的不同点主要有以下两点,我们可以从代码效果上去验证。

2.1.1 值类型的第二个变量改变不会影响第一个变量的值,因为两个变量使用的是不同的内存空间

        int a = 10;
        int b = a;
        b++;
        Console.WriteLine ("a = " + a);

2.1.2 引用类型的第二个变量的改变,会影响第一个变量的值,因为两个变量使用的是同一块内存空间

        int[] arr1 = { 1, 2, 3 };
        int[] arr2 = arr1;
        arr2 [0] = 4;
        arr2 [1] = 5;
        for (int i = 0; i < 3; i++) {
            Console.Write (arr1 [i] + " ");
        }

练习:将冒泡排序封装成方法,在当前类中还有打印输出数组所有元素的方法,随机为数组赋值的方法。并进行验证。

  • 定义方法
class SortedClass
{
    // 冒泡排序方法
    public void SortedArray (int[] arr)
    {
        int count = arr.Length;
        for (int i = 0; i < count - 1; i++) {
            for (int j = 0; j < count - 1 - i; j++) {
                if (arr [j] > arr [j + 1]) {
                    int temp = arr [j];
                    arr [j] = arr [j + 1];
                    arr [j + 1] = temp;
                }
            }
        }
    }
    // 输出数字所有元素的方法
    public void OutputArray (int[] arr)
    {
        for (int i = 0; i < arr.Length; i++) {
            Console.Write (arr [i] + " ");
        }
        Console.WriteLine ();
    }
    // 为数组元素赋随机值的方法
    public void RandomArray (int[] arr, int m, int n)
    {
        int count = arr.Length;
        Random ran = new Random ();
        for (int i = 0; i < count; i++) {
            arr [i] = ran.Next (m, n);
        }
    }
}
  • 调用验证
        static void Main(string[] args)
        {
            int[] array = { 9, 4, 1, 2, 6 };
            SortedClass sorted = new SortedClass();
            sorted.SortedArray(array);// 进行排序
            Console.WriteLine("排序后:");
            sorted.OutputArray(array);// 输出排序后的数组

            // 定义一个空数组,调用赋值方法,为数组元素赋随机值
            int[] temp = new int[10];
            sorted.RandomArray(temp, 10, 30);
            Console.WriteLine("排序之前的数组:");
            sorted.OutputArray(temp);
            sorted.SortedArray(temp);
            Console.WriteLine("排序后:");
            sorted.OutputArray(temp);
        }

三、方法的参数

C#中方法的参数有4种类型:

  • 值参数:不附加任何修饰符。
  • 引用参数:以ref修饰符声明。
  • 输出参数:以out修饰符声明,可返回一个或多个值给调用者。
  • 可变参数:以params修饰符声明,参数长度可变。

定义一个类MyClass,用来演示方法的参数:

    class MyClass
    {
        // 定义一个方法,用于交换两个变量的值
        public void ChangeValue (ref int a, ref int b)
        {
            int temp = a;
            a = b;
            b = temp;
        }
        // 定义一个方法,传入两个浮点数,分别返回这两个数的两倍
        public void DoubleOfFloat (float a, float b, out float res1, out float res2)
        {
            res1 = 2 * a;
            res2 = 2 * b;
        }

        // 定义一个方法,可以用来计算多个整数的和,整数个数可以不做限制
        public int Sum (params int[] arr)
        {
            int sum = 0;
            // 在方法内遍历可变参数,得到每一个元素,然后进行处理
            foreach (int temp in arr) {
                sum += temp;
            }
            return sum;
        }
    }

3.1 值参数

  • 在开始验证之前,首先在Main函数内对类进行实例化:
         MyClass mc = new MyClass ();
  • 定义一个方法,用于交换两个整形变量的值(先不添加ref)。因为形式参数的类型为值类型,所以两个变量的值并不会改变
         int a = 3, b = 4;
         mc.ChangeValue (a, b);

         Console.WriteLine ("a = {0}, b = {1}", a, b);

3.2 引用参数 -- ref

  • 将刚才定义的方法中的参数加上ref
  • ref关键字 定义引用类型的参数(将值类型转变为引用类型)
  • 注意:形参和实参前都需要加ref 关键字修饰
  • ref修饰的变量在传递参数前一定要有初始值
            int a = 3, b = 4;
            mc.ChangeValue (ref a, ref b);

            Console.WriteLine ("a = {0}, b = {1}", a, b);

3.3 输出参数 -- out

  • 方法最多只能有一个返回值,但某些情况下我们可能需要方法执行完以后,给我们返回多个结果,此时就可以使用输出参数out 关键字 修饰输出参数
  • 注意:形参和实参前都需要加 out 关键字修饰。被out 修饰的形参,必须在方法体内被赋值

定义一个方法,传入两个浮点数,分别返回这两个数的两倍:

            float a = 3.2f, b = 4.9f;
            float r1, r2;// 分别定义两个浮点型变量,作为浮点参数
            mc.DoubleOfFloat (a, b, out r1, out r2);

            Console.WriteLine ("r1 = {0}, r2 = {1}", r1, r2);

3.4 可变参数(必须是数组)-- params

  • 定义方法时不能确定调用方法时传递多少个参数,方法中使用遍历数组处理。
  • 可变参数的长度可变,长度可以为0
  • 可变参数只能使用一次,且放在参数列表的末尾,不能与ref、out同时使用

定义一个方法,可以用来计算多个整数的和,整数个数可以不做限制:

            int sum = mc.Sum (6, 8);
            Console.WriteLine ("sum = " + sum);
            sum = mc.Sum (1, 3, 5, 7, 9);
            Console.WriteLine ("sum = " + sum);
            sum = mc.Sum (11, 23, 5, 8, 9, 77, 99, 66);
            Console.WriteLine ("sum = " + sum);

练习:
1、交换三个整形变量的值(按由小到大的顺序交换),在 Main方法中输出结果。(要求用ref)
2、写一个方法,可以将数组按a[0]-a[1]+a[2]- a[3]+a[4]......的格式返回结果,在Main方法中调用该方法。 (参数要求用params修饰)

(自行练习,做题过程中有疑问可在群内交流。答案见下节。)

本次讲解就到这里,有关技术问题请小伙伴们添加QQ群:941928511,大家一起探讨!
版权声明:本文为博主原创文章,转载请附上原文出处链接和本声明

你可能感兴趣的:(C#基础- 属性 方法参数 数据类型-09)