C# 学习笔记(二)

C# 类型转换

类型转换就是从一种数据类型转换到另一种数据类型,有隐式类型转换和显式类型转换两种方式:

  • 隐式类型转换
    隐式类型转换是C#默认的安全转换方式,不会导致数据的丢失,隐式转换包括从精度较低的数据类型转换为精度较高的数据类型的情况,或者从派生类转换到基类。

  • 显式类型转换

    显式类型转换即强制类型转换,通过在数据名前使用强制转换运算符来实现。

具体的隐式转换和显式转换的一些例子如下所示:

using System;

namespace TypeConversionApplication {
  class TypeConversion {
    static void Main(string[] args) {
      /* 强制类型转换 */
      float f = 3.1415926F; // 注意要加上F,不然系统会默认为食double类型的浮点数
      int i;
      
      i = (int)f;
      
      Console.WriteLine("强制类型转换");
      Console.WriteLine(f);
      Console.WriteLine(i);
      /* 强制类型转换 */
      
      /* ------------------- */
      
      /* 隐式转换 */
      float fi = 3.14159;
      double di = fi;
      Console.WriteLine();
      Console.WriteLine("隐式类型转换");
      Console.WriteLine(fi);
      Console.WriteLine(di);
      
      // 失败情况,编译器报错
      // double dis = 3.14;
      // float fis = dis;
      /* 隐式转换 */
    }
  }
}

代码运行的结果如下图所示,可以观察到强制类型转换造成了数据的丢失,但是显示转换则不会,如下图所示:

img1

C#本身也提供了许多内置的数据类型转换方法,如ToByte(),ToString()等,如下:

using System;

namespace TypeConversionApplication
{
    class TypeConversion
    {
        static void Main(string[] args)
        {
            // ToString
            float f1 = 3.14159F;
            string s1 = f1.ToString();

            // ToFloat
            double d1 = Convert.ToDouble(f1);

            Console.WriteLine(s1);
            Console.WriteLine(d1);
        }
    }
}

运行的结果如下所示:

img2


C# 修饰符

C#有五种访问修饰符,如下表所示:

访问修饰符效果
public公开的、公共的,任何公有成员可被外部类访问
private私有的,即只能在当前类内进行访问,成员变量默认是private
protected受保护的,即只能由当前类内方法或者子类中进行访问
internal只能在当前项目中进行访问,类如果不加修饰符的话,默认是internal
protected internalprotected internal

几点注意的事项:

  • 类的修饰符只能是publicinternal
  • 子类的访问权限不能高于父类的访问权限

C#循环

C#的循环主要有for和foreach两种形式,可以在下述冒泡排序的代码中复习下:

using System;

namespace CycleApplication
{
    class Calculater
    {
        static void Main(string[] args)
        {
            int[] arr = { 3, 5, 2, 4, 7, 9, 8, 0, 1, 3 };
            bubbleSort(arr);
            foreach (int i in arr)
            {
                Console.Write(String.Format("{0, -2}", i));
            }
            Console.WriteLine();
        }

        static void bubbleSort(int[] arr)
        {
            for (int i = 0; i < arr.Length; i++)
            {
                for (int j = 0; j < arr.Length - i - 1; j++)
                {
                    if (arr[j] > arr[j+1])
                    {
                        int tmp = arr[j];
                        arr[j] = arr[j+1];
                        arr[j+1] = tmp;
                    }
                }
            }
        }
    }
}

关于格式化输出,参见https://www.cnblogs.com/arxive/p/5744823.html

关于方法调用的过程,跟C++是差不多,手撕快排学习一下:

using System;

namespace quickSortApplication
{
    class quickSortSet
    {
        public void swap(ref int a, ref int b)
        {
            int tmp = a;
            a = b;
            b = tmp;
        }

        public void quicksort(int[] arr, int start, int end)
        {
            if (start < end)
            {
                int i = start;
                int j = end;
                int key = arr[i];
                while (i < j)
                {
                    while (i < j && arr[j] > key)
                    {
                        j--;
                    }

                    if (i < j)
                    {
                        swap(ref arr[i], ref arr[j]);
                        i++;
                    }

                    while (i < j && arr[i] < key)
                    {
                        i++;
                    }

                    if (i < j)
                    {
                        swap(ref arr[i], ref arr[j]);
                        j--;
                    }
                }
                quicksort(arr, start, i - 1);
                quicksort(arr, i + 1, end);
            }
        }

        static void Main(string[] args)
        {
            int[] arr = { 2, 3, 1, 6, 4, 8, 5, 9, 1, 0 };
            quickSortSet qs = new quickSortSet();
            qs.quicksort(arr, 0, 9);
            foreach (int i in arr)
            {
                Console.Write(String.Format("{0, -2}", i));
            }
            Console.WriteLine();
        }
    }
}

C# Nullable

单问号?用于为无法直接赋值为null的数据类型如int,double,bool进行数据类型的赋值。

双问号??用于判断一个数据为null时的返回值。

试下下面的事例代码:

using System;

namespace NullableApplication
{
    class NullableTest
    {
        static void Main(string[] args)
        {
            double? num1 = null;
            double? num2 = 3.14159;
            double num3 = 3.14;
            Console.WriteLine(num1);
            Console.WriteLine(num2);
            Console.WriteLine(num3);

            num3 = num1 ?? 5.35;
            Console.WriteLine(num3);
        }
    }
}

代码的执行结果如下所示:

img3


C# 字符串

字符串的最好入门就是多多使用:

using System;

namespace StringApplication
{
    class StringApp
    {
        static void Main(String[] args)
        {
            string str1 = " I am ";
            string str2 = " Alva";

            /* Trim */
            str1 = str1.Trim();
            Console.WriteLine(String.Format("Str1 after triming: {0}", str1));

            string str3 = string.Concat(str1, str2);
            Console.WriteLine(String.Format("Concat str1 and str2: {0}", str3));

            Console.WriteLine(String.Format("Index1 : {0}", str3[0]));
            Console.WriteLine(String.Format("Find Index: {0}", str3));
            Console.WriteLine(String.Format("ToUpper: {0}", str3.ToUpper()));
            Console.WriteLine(String.Format("ToLower: {0}", str3.ToLower()));
        }
    }
}

代码的执行结果如下所示:

img9


C#枚举

枚举型enum,枚举列表中的每个数代表一个整数值,默认情况下第一个枚举符号的值时0。

using System;

namespace EnumApplication {
  class EnumTest {
    enum Day {Mon, Tus, Wes, Thr, Fri, Sat, Sun};
    int Monday = (int)Day.Mon;
    Console.WriteLine(Monday);
  }
}

代码的执行结果如下所示:

img10

C#继承

私以为继承、多态这些跟C++非常相似,自己也写过Java,感觉还是自己写两份Demo熟悉下就会比较快掌握了,C#不支持多重继承,但是可以通过接口来实现多重继承。

首先写一段继承的代码玩玩:

using System;

namespace InheritantApplication
{
    enum Gentle { male, female };

    class Person
    {
        protected string name { get; set; }
        protected Gentle gentle { get; set; }
        protected int age { get; set; }

        public Person(string _name, Gentle _gentle, int _age)
        {
            name = _name;
            gentle = _gentle;
            age = _age;
        }
    }

    class Student : Person
    {
        protected string major { get; set; }

        public Student(string _name, Gentle _gentle, int _age, string _major) : base(_name, _gentle, _age)
        {
            major = _major;
        }

        public override string ToString()
        {
            return $"Student information: \n" +
                   $"Name  : {name}\n" +
                   $"Gentle: {gentle}\n" +
                   $"Age   : {age}\n" +
                   $"Major : {major}";
        }
    }

    class ExecuteInhritant
    {
        static void Main(string[] args)
        {
            Student student1 = new Student("Alva", Gentle.male, 22, "SE");
            string Info = student1.ToString();
            Console.WriteLine(Info);
        }
    }
}

执行上面的代码,可以打印出自己期望的输出信息:

img11

C#的enum测试了下,好像是可以直接输出定义的时候的字段的,如Gentle.male输出的是male,如果想输出0的话,就需要做一部强制类型转换。

多态

多态是C++中老生常谈的面试题,所以自己还是比较熟悉的,多态主要有编译时多态和运行时多态,编译时多态包括函数重载和泛型编程,而运行时多态即在类中实现的多态,通过虚函数来进行实现。

抽象类

抽象类的一些特点:

  • 不能创建一个抽象类的实例
  • 不能在抽象类外面声明抽象方法
  • 在类前面的关键字sealed表明类不能被继承,但是抽象类不能够被sealed修饰

编写一个简单的抽象类来熟悉语法:

using System;

namespace InheritantApplication
{
    abstract class Animal
    {
        abstract public void bark();
    }

    class Dog : Animal
    {
        public override void bark()
        {
            Console.WriteLine("Wang Wang!");
        }
    }

    class Cat : Animal
    {
        public override void bark()
        {
            Console.WriteLine("Miao Miao!");
        }
    }

    class ExecuteAnimal
    {
        static void Main(string[] args)
        {
            Cat cat = new Cat();
            cat.bark();

            Dog dog = new Dog();
            dog.bark();
        }
    }
}

程序的运行结果如下所示,可见实现了多态:

img12

当然,如果不使用抽象类来实现多态的话,也可以用虚函数来实现,具体的方法就是在基类相应的函数前加上virtual关键字,C#不支持多继承,因此抽象类只能够单继承。

接口

  • 如果接口继承了其他接口,那么所以继承接口的方法都需要实现。
  • 接口的命名通常以I开头。
  • 接口不能用public、abstract等修饰符进行修饰,不能有字段变量、构造函数。
  • 接口内可以定义属性。
  • 接口能够解决C#多继承问题。

简单异常处理

异常处理跟C++的基本上差不多,自己也没怎么深入,所以就随便写一段代码来学习一下:

using System;

namespace ExceptionApplication
{
    class MyException : Exception
    {
        public void print()
        {
            Console.WriteLine("Hellow World!");
        }
    }

    class ExecuteApp
    {
        static void Main(string[] args)
        {
            try
            {
                throw new MyException();
            }
            catch (MyException e)
            {
                e.print();
            }
            finally {
                Console.WriteLine("Hi!");
            }
        }
    }
}

img14

Reference

https://www.cnblogs.com/zsongs/p/5071748.html


版权声明:本文为Alva112358原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。