C#面向对象编程

类和对象

:描述某种事物的共同特征。
对象(类的实例):对象是类的一个实际的例子,简称实例。
实例化是从类创建对象的过程。
例:R1SE组合是一个类,里面的每个个体成员是该组合的一个对象。

类用来定义对象具有的特征(字段,属性)和可执行的操作(方法,事件)。
类的成员:属性(做什么,访问对象具有的特征),方法(如何做,处理对象的行为),事件(什么时候做,引发对象的动作),常量,字段,属性,索引,运算符,构造函数,析构函数,嵌套类。

在这里插入图片描述
例:

        public class Person
        {
            public string ID { get; set; }//get set指ID的属性,读写/加private set只读
            public string Name { get; set; }
        }
        public class Student:Person
        {
            private int age;
            public int Grade { get; set; }
            public  Student() { }
        }

这段代码定义了一个Person类,一个继承Person的Student类。
public是修饰访问符
age是字段
ID、Name、Grade都是属性
Student()是Student类的构造函数

修饰访问符

类的访问修饰符用于控制类的访问权限,成员的访问修饰符用于控制类中成员的访问权限。

常用访问修饰符:
(1)public:类的内部和外部代码都可访问。
(2)private:类的内部可访问,类的外部无法访问。
(3)internal:同一个程序集中的代码都可以访问,程序集外的其他代码则无法访问。
定义一个类时,如果省略类的访问修饰符,默认为internal;如果省略类成员的访问修饰符,默认为private。

用于类继承的访问修饰符:
(1)protected:类的内部或者从该类继承的子类可以访问。
(2)protected internal:从该类的子类或者从另一个程序集中继承的类都可以访问。

字段

类的成员变量,字段可以在类的所有方法和事件中访问,作用域在类的内部,类的外部无法访问变量,可以通过this关键字访问;局部变量不能用this访问。

只读字段:readonly
在程序运行期间只能初始化一次的字段。
初始化方式:
1.在声明语句中初始化;2.在构造函数中初始化。

public class A
{
   readonly int a = 3;
   readonly string ID;
   public A()
   {
       ID = "19980528";
    }
 }   

若在readonly前加static,作用就像const声明一个常量。

public static readonly int a =3
构造函数

构造函数是创建对象时自动调用的函数,一般在构造函数中初始化工作,或者一些仅需执行一次的特定操作。
每个类至少有一个构造函数,如果没有声明,系统会自动提供一个不带参的。(默认构造函数)

实例构造函数
public class Person
        {
            public  Person() { }
        }

初始化类中的实例变量,它只有在用户用new关键字时才被调用。而且作为引用类型的类;

new关键字
  1. 创建对象
    new关键字指明要调用的是那个构造函数,用于创建类的实例对象和其属性。
    例:
    第一个创建的是s,调用的是Person()实例构造函数。
    第二个创建的是p1,调用Person类中不带参数的构造函数,同时初始化ID和Name两个属性。
var s = new Person();

Person p1 = new Person() { ID = "006", Name = "翟潇闻"};

在创建一个类的实例时,一是使用new关键字要求系统为该对象分配内存,而是指明调用的是哪个构造函数。

  1. 对象初始化
    用一条语句同时实现创建对象和初始化属性。
    例:直接创建s,并初始化Name,Grade两个属性。
StudentInfo s = new StudentInfo() { Name = "张颜齐", Grade="89" };
//等同于
StudentInfo s = new StudentInfo("张颜齐","89");//实例化一个StudentInfo对象
//注:传递给构造函数的参数是实参就是真正的数据,实参,并创建完以后调用构造方法

实例化对象,其实就是创建对象过程;
要用一个类中的一个方法。如果这个类是静态类,可以直接调用这个方法。
如果这个类不是静态类,就需要用对象来引用这个方法。
那么对象如何来呢?就需要new一下了。
例:B类要调用,A类中的 Method1()方法。那么在调用这个方法之前,必须要要创建A的对象m。
A m = new A();
调用 m.Method1();

this关键字
  1. 访问对象
    this.实例名,访问当前对象。

  2. 作为参数传递

等找到例子再补充…

static关键字

通过指定类名调用静态成员,通过指定实例名来调用实例成员。
如果有些成员是所有对象共用的,此时可以将这些成员定义为静态的(static)。当该类被装入内存时,系统就会专门开辟一部份区域保存这些静态成员,在内存中只存有一份。

static可以用于类、字段、方法、属性、运算符、事件和构造函数。

静态方法可以被重载但不能被重写,因为它们属于类,而不是类的实例。

用static声明的静态成员在外部只能通过类名称来引用,不能用实例名。

实例名是指 : 先 Class1 c = new Class1(); 再通过c.x 或者c.Method();
例:
这里的Class1.x = 5; Class1.Method(); 都是直接引用了类名来调用其静态成员。

  class Class1
        {
            public static int x = 100;
            public static void Method()
            {
                Console.WriteLine(x);
            }
        }
        class Program
        {
            static void Main(string[] args)
            {
                Class1.x = 5;
                Class1.Method();
            }
        }
静态构造函数

静态构造函数用于初始化任何 静态 数据,或用于执行仅需执行一次的特定操作。 在创建第一个实例或引用任何静态成员之前,将自动调用静态构造函数。

  • 既没有访问修饰符,也没有参数。
  • 静态构造函数是在实例构造函数之前执行的
  • 程序员无法直接调用静态构造函数
  • 静态构造函数只能调用一次

静态类

  • 仅包含静态成员
  • 无法实例化
  • 不能被继承
  • 不能包含实例构造函数,但可以包含静态构造函数

构造函数例子

Loaded += delegate
            {
                C03.Hello1();//通过调用类名,访问静态方法hello1,静态构造函数会被自动调用
                var c = new C03();//new一个对象c,实例化对象,此时已经调用了实例化构造函数
                c.Hello2();//通过c调用Hello2方法
                uc.Result.Content = C03.Result;
                //输出整个四句话
            };
        }
    }
    class C03
    {
        public static string Result { get; set; } = "";
        static C03()
        {
            Result += "静态构造函数\t";
        }

        public C03()
        {
            Result += "实例构造函数\t";
        }

        public static void Hello1()
        {
            Result += "静态方法\n";
        }

        public void Hello2()
        {
            Result += "实例方法\n";
        }

静态函数自动调用,接着c.Hello1调用静态方法,然后new一个对象的时候调用了实例构造函数,最后C.Hello2调用实例方法。
运行如图
在这里插入图片描述

方法

在面向对象编程中,除了构造函数比较特殊叫做函数,其他的单独实现的功能的叫做方法。

 public int  Add(int x,int y = 10)
        {
            return x + y;
        }
        
 public void Methon()
        {
            Console.WriteLine("12345");
        }

方法中的参数传递

  1. 值参数
    用于传递输入参数,一个值参数相当于一个局部变量。
//<summary>方法(1)——值参
        public int Add(int x,int y = 10)
        {
            return x + y;
        }
  1. ref关键字(引用参数)
    用于传递输入和输出参数,为引用参数传递的实参必须是变量。
//<summary>方法(2)——ref关键字
        public void AddOne(ref int a)
        {
            a++;
        }

3.out关键字(输出参数)
用于传递返回的参数,与引用参数用法类似。由于return一次只能返回一个结果,out关键字也可以实现返回多个结果。

//<summary>方法(3)——out关键字
        public void Div(int x,int y,out int result,out int remainder)
        {
            result = x / y;
            remainder = x % y;
        }
  1. params关键字(数组参数)
    用于向方法传递可变数目的实参。
//<summary>方法(4)——params关键字
        public double? Average(params int[] v)
        {
            if (v.Length == 0)
            {
                return null;
            }
            double total = 0;
            for (int i = 0; i < v.Length; i++) total += v[i];
            return total / v.Length;
        }

方法例子

public E04Method()
        {
            InitializeComponent();
            Loaded += delegate
            {
                var c = new C04();
                uc.Result.Content = c.R;
            };
        }
  class C04
    {
        public string R { get; } = string.Empty;
        public C04()
        {
            //
            int a = 20, b = 30, c = 0;
            var v1 = Add(a);
            var v2 =Add(a, b);//传两个值,覆盖了原来的初值
            R += $"方法1(值参):a={a},b={b},c={c},v1={v1},v2={v2}";

            //
            int x = 0;
            R += $"\n方法2(ref):调用前x的值为{x},";
            AddOne(ref x);//传入一个变量,对变量进行操作
            R += $"调用后x的值为{x},";

            //
            int x1 = 13, y1 = 3;
            Div(x1, y1, out int r1, out int r2);
            R += $"\n方法3(out):x1={x1},y1={y1},商={r1},余数={r2}";
            //作用是输出多个结果

            //
            string s1 = $"1,2,3,5的平均值为{Average(1, 2, 3, 5)}";
            string s2 = $"4,5,6的平均值为{Average(4, 5, 6)}";
            string s3 = $"元素个数为零时结果是否为有效值:{Average().HasValue}";
            R += $"\n方法4(params):\n{s1}\n{s2}\n{s3}";
        }

        //<summary>方法(1)——值参
        public int Add(int x,int y = 10)
        {
            return x + y;
        }
        //<summary>方法(2)——ref关键字
        public void AddOne(ref int a)
        {
            a++;
        }
        //<summary>方法(3)——out关键字
        public void Div(int x,int y,out int result,out int remainder)
        {
            result = x / y;
            remainder = x % y;
        }
        //<summary>方法(4)——params关键字
        public double? Average(params int[] v)
        {
            if (v.Length == 0)
            {
                return null;
            }
            double total = 0;
            for (int i = 0; i < v.Length; i++) total += v[i];
            return total / v.Length;
        }
    }

运行结果:
在这里插入图片描述
Lambda表达式:
在这里插入图片描述
在这里插入图片描述

 string Demo1() => "hello";
 int Demo2(int x, int y) => x + y;
 string s = $"Demo1:{Demo1()}\t Demo2:{(13, 14)}";
属性

常规属性声明:

class Student
{
    private int age;
    public int Age
    {
        get { return age; }
        set { if (value >= 0) age = value; }
    }

get访问器相当于一个具有属性类型返回值的无形参的方法。在引用属性时,会自动调用该属性的get访问器以计算该属性的值。(表示“读”)
set访问器相当于具有一个名为value的参数并且没有返回类型的方法。(表示“写”)

class Student
{
    public int Age{get; private set; }
    public string Name { get; set; }
 }

Age是只读属性,Name是读写属性

委托

任何类或者对象中的方法都可以通过委托来调用,但要先声明委托的名称以及他要调用的方法的参数和返回类型,及方法签名。
可以看作一个指针,指向内存的一个地址,当调用方法时,放入该位置。
委托示例:

 public E07Delegate()
        {
            InitializeComponent();
            Loaded += delegate
            {
                var d1 = new DelegateDemo();
                uc.Result.Content = d1.R;
            };
        }
  public class DelegateDemo
    {
        public string R { get; set; } = "";//声明输出的变量R
        public DelegateDemo()//构造函数,里面放两个调用的方法
        {
            Demo1();  //基本用法
            Demo2();  //将委托作为参数传递给另一个方法(实际用途)
        }
        public void Demo1()
        {
            //用法1:调用类的静态方法
            MyDelegate m1 = MyClass.Method1;//静态时候直接通过类名调用静态方法Methon1()
            double r1 = m1(10);
            R += $"r1={r1:f2}";
            
            //用法2:调用类的实例方法
            var c = new MyClass();//创建类的实例
            MyDelegate m2 = c.Method2;//用创建的实例来调用实例构造函数中的方法
            double r2 = m2(5);
            R += $",r2={r2:f2}\n";
        }
        
        public void Demo2()
        {
            MyClass c = new MyClass();
            double[] a = { 0.0, 0.5, 1.0 };

            //利用委托求数组a中每个元素的正弦值
            double[] r1 = c.Method3(a, Math.Sin);
            foreach (var v in r1)
            {

            }
            R += $"r1={string.Join(",", r1)}\n";

            //利用委托求数组a中每个元素的余弦值
            double[] r2 = c.Method3(a, Math.Cos);
            R += $"r2={string.Join(",", r2)}\n";
        }
    }
    
    public delegate double MyDelegate(double x);
    //声明一个委托MyDelegate 定义为double类型
    
    public class MyClass
    {
        public static double Method1(double x)
        {
            return x * 2;
        }
        public double Method2(double x)
        {
            return x * x;
        }
        //遍历数组,并创建一个和原数组长度相同的,存放新的元素
        public double[] Method3(double[] a, MyDelegate f)
        {
            double[] y = new double[a.Length];
            for (int i = 0; i < a.Length; i++)
            {
                y[i] = f(a[i]);
            }
            return y;
        }
    }

运行结果:
在这里插入图片描述

事件

时间在本质上是通过委托实现的,所以在事件之前需要声明一个委托。

public delegate void MyEventHandler();
public event MyEventHandler Handler;

若要引发事件,可以定义引发该事件时要调用的方法

public void OnHandler()
{   
       Handler();
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值