C#学习笔记1(C#与C++相关的部分)

C#简介

C#区别于C++与C,他是一门纯面向对象的语言,那么什么是面向对象的语言呢?有跟面向过程有什么区别呢?

面向过程:它是一种编程范式,它将程序视为一系列的过程或函数的集合。

面向对象:它是也是一种常用的编程范式,它将程序设计建立在对象的概念上。那么讲到面向对象就离不开它三大特征了,封装、继承、多态。

什么是封装、继承和多态

1.封装

将对象的状态和行为封装在一起,通过限制对内部数据和方法的直接访问,提供了更好的安全性和灵活性。

封装属性和字段

属性是类,结构体,接口的命名成员,类或者结构体中的成员变量及方法称为域,属性是域的扩展

简单点说:属性就是方法(成员函数),字段就是数据成员。字段如果不赋初值的话系统会给其一个null。

//学生类
class Student
    {
        private string name;
        //属性
        public string Name
        {
            get { return name; }
            set { name = value; }
        }
        //系统能够自己分清给的是那个字段的数据
        public int Code
        {
            get;
            set;
        }

        private int age;

    }
2.继承

通过继承机制,一个类可以派生出子类没从而继承父类的属性和方法。继承促进了代码重用和扩展,使得代码更易于维护和扩展。

单继承类(class),多继承接口(interface)
base
1.在派生类中调用基类的构造函数
2.在子类中调用基类的方法
3.注意:静态函数中禁止使用base关键字

//图形基类
    class Shape
    {

        protected int width;
        private int length;
        protected int Length
        {
            get { return length; }
            set { length = value; }
        }
        public Shape()
        {
            Console.WriteLine("父类构造");
        }
        public void Test2()
        {
            Console.WriteLine("父类的测试方法");
        }
    }
//长方形子类
    class Rectangle : Shape
    {
        public int GetArea()
        {
            return Length * width;
        }
        public Rectangle()
            : base()//在派生类中调用基类的构造函数
        {
            Console.WriteLine("子类构造");
        }
        public void Test()
        {
            base.Test2();//调用基类中的方法
            Console.WriteLine("子类的测试方法");
        }
//不要再静态方法里使用base
        //public static void Test3()
        //{
        //    base.Test2();
        //}
    }
2.多态

多态允许不同的对象对同一个消息做出不同的响应。通过多态,可以编写出更通用、灵活和可扩展的代码。多态又分为静态多态和动态多态。

什么是静态多态,什么是动态多态

1.静态多态
          函数重载:参数类型不同,参数的个数不同,不能重载只有返回值类型不同的函数
  运算符重载:operator

C#中可重载的运算符:
         + - * / %
         ++ -- ! ~ 
         == > < >= <= !=
  

//静态多态
class TestData
    {
//函数重载
        public int Add(int a, int b)
        {
            return a + b;
        }
        
        public double Add(double a, double b)
        {
            return a + b;
        }
//这不是函数重载,因为其只有返回值类型不同
        public float Add(int a, int b)
        {
            return a + b;
        }

        public int num;

        //运算符重载
        public static TestData operator +(TestData t1, TestData t2)
        {
            TestData t = new TestData();
            t.num = t1.num + t2.num;
            return t;
        }
    }


 不能重载的运算符
         = -> . new sizeof ?: += -= *= /= %=
  2.动态多态
  虚函数,抽象类 关键字abstract (抽象类中可以定义普通的成员方法)
  1.不能创建抽象类的实例
  2.抽象类中可以声明抽象函数和非抽象函数,但是非抽象类不能声明抽象函数

//动态多态
//抽象类  关键字abstract
abstract class Animal
    {
        public abstract void Eat();
        public virtual void Test()
        {
            Console.WriteLine("抽象类中的普通函数");
        }
    }
class Lion : Animal
    {
        //public abstract void TestMethod();
        public override void Eat()
        {
            Console.WriteLine("子类的吃");
        }
        public override void Test()
        {
            base.Test();
            Console.WriteLine("重写父类中的test函数");
        }
    }

C#的访问权限

C#不同与C++,它有四种访问权限:

private:只能在类中访问
public:公有的,在任意程序集(一个项目)中都能访问
protected:只能在当前程序集的类中和子类中访问
internal:只能在当前程序集类中和类外访问
protected internal:protected or internal,既可以在当前程序集的子类和类中访问,也可以只在当前程序集的类中和类外访问

既然提到了程序集,那什么是程序集呢?

程序集:类型元数据,程序集元数据,IL代码,资源
元数据:元数据一般就是指描述自身的数据
程序集元数据:包含程序集的扳本信息,安全信息,签名等
类型元数据:记录程序集引用了哪些类,用户自定义了哪些类,字段,数据类型等一系列信息
IL代码:c#->IL代码->保存到程序集中,被CLR加载,通过JIT调用BCL->机器码,在CPU运行
资源:图片,声音,视频等

C#的变量

值类型和引用类型

 值类型:值类型的变量直接存储数据。值类型包括: int float byte long short double char bool struct
 引用类型:引用类型的变量持有的是数据引用(地址),数据是存储在堆区的。引用类型包括:class string 委托 事件

值类型与引用类型区别:
1.值类型数据存储在栈区,引用类型的数据存储在堆区
2.值类型存取速度快,引用类型存取速度慢
3.值类型表示的是实际的数据,引用类型表示的指向存储在堆区的地址
4.值类型继承自system.valuetype,引用类型继承自system.object
5.栈区内存是自动释放,堆区内存由GC回收

什么是GC(垃圾回收机制)

在编写程序时,会产生很多的数据 比如:string 变量,这些数据都存储在堆区里,如果不合理的管理他们,就会内存溢出导致程序崩溃

C#内置了自动垃圾回收GC,在编写代码时可以不需要担心内存溢出的问题 变量失去引用后 GC会帮我们自动回收,但不包括数据流,和一些数据库的连接,这就需要我们手动的释放资源

GC是一种自动化内存管理机制,负责在程序运行时跟踪并管理对象的内存使用情况,当对象不再被引用时,自动从内存中删除这些对象,并释放内存

GC的作用:让内存的利用率更高。
特点:
1.自动管理
2.分代回收 代龄  高效,朝生夕灭,只有少部分的对象会长时间存在
3.不确定性 GC.Collect()
4.gc会影响程序的性能
5.gc只回收堆区内存,栈区内存是使用后自动释放

C#中的循环

循环语句

while  do...while for  foreach

foreach的语法形式:

foreach(var item in collection)

{

}

foreach的优缺点:

优点:
1.foreach语法简洁,多维数组遍历只需要一行代码,for循序需要给初始值,步长,结束值,foreach不需要,会自动遍历集合中的所有值
2.foreach的效率比for循环高,foreach遍历速度比for要快
3.不需要关心数组的起始值
缺点:
1.会造成额外gc开销
2.foreach是只读类型

因此在知道循环的长度时,尽量用for循环而不用foreach

class Program
    {
        static void Main(string[] args)
        {
            //C++中定义数组
            //int a[10]={1,2,};
            //C#中数组的定义形式
            int[] a1 = { 1, 2, 3 };
            int[] a2 = new int[3] { 1, 2, 3 };
            int[] a3 = new int[] { 1, 2, 3 };
            int[,] a4 = new int[,] { { 1, 2 }, { 3, 4 } };
            int[,] a5 = new int[2, 2] { { 1, 2 }, { 3, 4 } };
            //for循环的定义形式   a1.Length能的到a1的长度
            for (int i = 0; i < a1.Length; i++)
            {
                Console.WriteLine(a1[i]);
                a1[i] = 6;
            }
            for (int i = 0; i < a4.GetLength(0); i++)
            {
                for (int j = 0; j < a4.GetLength(1); j++)
                {
                    Console.WriteLine(a4[i, j]);
                }
            }
            //foreach循环的定义形式
            foreach (int item in a1)
            {
                Console.WriteLine(item);
            }
            foreach (int item in a4)
            {
                Console.WriteLine(item);
            }

        }
    }

C#中的函数

函数中的参数

如果我们想C++那样传递引用类型,C#中提供了专门的关键字refout
相同点:都是址传递,执行方法后,原来的值会改变
不同点:
1.使用ref时,传入参数必须要初始化,而使用out时参数可以不初始化
2.ref的参数可以不赋值,但是out参数必须要赋值

class Program
    {
        static void Main(string[] args)
        {
           
            Test t = new Test();
            int a = 1, b = 2;
            //Console.WriteLine("a={0},b={1}", a, b);
            //t.TestOut(out a, out b);
            //Console.WriteLine("a={0},b={1}", a, b);

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

    class Test
    {
        //out的蚕食必须在函数体中完成初始化
        public void TestOut(out int a, out int b)
        {
            a = 10;
            b = 20;
        }
        //传入的参数必须已经初始化
        public void TestRef(ref int a, ref int b)
        {
            //a = 30;
            //b = 40;
        }
    }

override与new关键字

override:重写基类中的方法(virtual,abstract)

new:

1.创建对象
2.在子类中使用new关键字,修饰定义与父类中同名的函数,叫覆盖,覆盖不会改变父类的方法功能

class Program
    {
        static void Main(string[] args)
        {
            A aaa = new A();
            aaa.Test();
            B bbb = new B();
            bbb.Test();
            A aaaaaa = new B();
            aaaaaa.Test();
        }
    }
class A
    {
        public virtual void Test()
        {
            Console.WriteLine("a类的测试函数");
        }
    }
    class B : A
    {
        //public override void Test() //当用子类创建父类时, A aaaaaa = new B();调用子类的函数
        //{
        //    Console.WriteLine("b类的测试函数");
        //}
        //当用子类创建父类时, A aaaaaa = new B();覆盖是不会改变父类的功能,仍然调用父类的函数
        public new void Test()
        {
            Console.WriteLine("b类的测试函数");
        }
    }

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值