C#核心——面向对象:封装

成员变量------特征

成员方法------行为

构造函数

无参构造函数

类中是允许自己声明无参构造函数的,而结构体是不允许的

复制代码
class Person
{
    public string name;
    public int age;

    //无参构造函数
    public Person()
    {
        name = "唐老狮";
        age = 18;
    }
}

class Program
{
    static void Main(string[] args)
    {
        Console.WriteLine("构造函数和析构函数");

        Person p = new Person();//调用无参构造函数
        Console.WriteLine(p.age);
    }
}

重载构造函数

复制代码
public Person(int age)
{
    //this代表当前调用该函数的对象自己
    //当传入参数名字与成员变量名字相同时,需要用this区分哪个参数是对象参数
    this.age = age;
}

public Person(string name)
{
    this.name = name;
}

public Person(int age, string name)
{
    this.age = age;
    this.name = name;
}

特殊构造函数

this括号里面是哪个参数,那就先执行哪个构造函数,再来执行冒号前面的构造参数

复制代码
//这里如果这么声明,this()会先默认调用无参构造函数
public Person(int age, string name): this()
{
    Console.WriteLine("Person两个参数构造函数调用");
}

//无参构造函数
    public Person()
    {
        name = "唐老狮";
        age = 18;
    }


//这里如果这么声明,this(name)会先默认调用传参(name)的构造函数
public Person(int age, string name): this()
{
    Console.WriteLine("Person两个参数构造函数调用");
}

public Person(string name)
{
    this.name = name;
}

成员属性

用于保护成员变量,为成员属性的获取和赋值添加逻辑处理------解决3p局限性问题(private/public/protected)

这里的使用核心是get return一个对应变量 ,set 使用一个value赋值。

cs 复制代码
class Person
{
    private string _name; // 私有字段

    public string Name // 公共属性
    {
        get { return _name; }
        set { _name = value; }
    }

    // 或者使用自动实现属性(更简洁)
    // public string Name { get; set; }
}

class Program
{
    static void Main(string[] args)
    {
        
        Person p = new Person();
        p.Name = "唐老狮";
   
    }
}

简单说说这里如何处理3p局限性

cs 复制代码
1、首先这里是public访问权限,里面不能get和set都是private
2、如果get 是private,就不允许外部获取;如果set 是private,就不允许外部修改

public int Money
{
    private get  
    {
        // 解密处理
        return money - 5;
    }
    set
    {
        // 加密处理
        money = value + 5;
    }
}

成员属性加密处理

这里可能还是会用函数进行加密,防止value数值直接被拆包然后修改?

cs 复制代码
public int Money
{
    get
    {
        // 解密处理
        return money - 5;
    }
    set
    {
        // 加密处理
        money = value + 5;
    }
}

自动属性

如果类中有一个特征是:只希望外部获取而不希望外部修改的

cs 复制代码
public float Height
{
    get;
    private set;
}

静态成员

从如下代码你可以发现,你使用静态类并没有实例化一个类作为对象使用,而是直接使用类名进行调用了

特点:不用new一个,可以直接类名点出来

cs 复制代码
class MyCalss
{
    public static float PI = 3.1415926f;
    
    public static float AreaOfCircle (float r)
    {
        return Person.PI * r * r;
    }
}


float areaCircle =  MyCalss.AreaOfCircle(7);

为什么可以直接使用类名就能用?

**静态成员的特点 :**程序开始运行时 就会分配内存空间------这也注定了静态成员具有唯一性(即任何修改就是修改其本身,任何地方都是使用它内存中的内容,修改也是修改其内存内容)

而实例化也是通过new分配内存空间

**特点2:**静态成员与程序同生共死

特点3静态函数中不能使用非静态成员(生命周期的差异)

cs 复制代码
class Test
{
    //静态成员变量
    static public float PI = 3.1415926f;

    //成员变量
    public int testInt = 100;

    //静态成员方法
    public static float CalcCircle(float r)
    {      
        return PI * r * r;
        如果这里直接使用testInt会报错,因为Test类还未被实例化
        
        正确方法:
        Test t=new Test();
        Console.WriteLine(t.testInt);
    }

    //成员方法
    public void TestFun()
    {
        Console.WriteLine("123");
    }
}

特点4:非静态函数可以使用静态成员

因为这是生命周期的缘故,静态成员从程序一开始就出现了,成员可以直接被函数使用

静态变量的作用

静态变量:

1.常用唯一变量的申明

2.方便别人获取的对象申明

如单例模式

静态方法:

1.常用的唯一的方法申明

比如 相同规则的数学计算相关函数

静态类

使用static关键字修饰的类,只能包含静态成员

不能被实例化 具有唯一性 适合用作工具类(计算公式 等)

cs 复制代码
static class Tools
{
    // 静态成员变量
    public static int testIndex = 0;

    // 静态方法
    public static void TestFun()
    {
        // 方法体为空
    }

    // 静态属性(带 get/set)
    public static int TestIndex
    {
        get;
        set;
    }
}

静态类的静态构造函数

使用static关键字修饰的构造函数,无访问修饰符 无参数

**什么时候被调用:**自动调用一次,只要是第一次使用静态构造函数中的静态成员,就会自动调用

作用: 主要用于初始化静态成员。

静态类和普通类中的静态构造函数功能一样,调用类时都会优先执行静态构造函数进行初始化

与构造函数(针对实例对象)不同的是,静态构造函数(针对类)只执行一次 ,并且是在第一个实例对象创建前被调用 ,所以它可以用于那些只需要执行一次的操作;而且它不允许有public等修饰符,由程序自动调用,不能被外界调用。

cs 复制代码
static class StaticClass
{
    public static int testInt = 100;
    public static int testInt2 = 100;

    static StaticClass()
    {
        Console.WriteLine("静态构造函数");
        testInt = 200;
        testInt2 = 300;
    }
}

class Program
{
    static void Main(string[] args)
    {
        Console.WriteLine("静态类和静态构造函数!");

        Console.WriteLine(StaticClass.testInt);
        Console.WriteLine(StaticClass.testInt2);
        Console.WriteLine(StaticClass.testInt); // 重复输出 testInt
    }
}

普通类的静态构造函数

cs 复制代码
class Test
{
    public static int testInt = 200;

    static Test()
    {
        Console.WriteLine("静态构造");
    }

    public Test()
    {
        Console.WriteLine("普通构造");
    }
}

class Program
{
    static void Main(string[] args)
    {
        Console.WriteLine(Test.testInt);
        Test t = new Test();
        Test t2 = new Test();
    }
}

意味着使用这个普通类中的成员,也就会自动调用这个类中的静态构造函数

静态构造函数的误解点

之前这里我如果把 public static int testInt = 200;变为普通成员变量public int testInt = 200

Console.WriteLine(Test.testInt);会报错------我误以为是静态构造函数必须要搭配静态成员

cs 复制代码
class Test
{
    public static int testInt = 200;
    public int testInt2 = 300;

    static Test()
    {
        Console.WriteLine("静态构造");
    }

    public Test()
    {
        Console.WriteLine("普通构造");
    }
}

class Program
{
    static void Main(string[] args)
    {
        Console.WriteLine(Test.testInt);
        Test t = new Test();
        Test t2 = new Test();
    }
}

是因为这里使用了静态成员的调用方式------直接使用类名+静态成员变量:Test.testInt

但此时这里testInt已经不是静态成员了,不可使用此方式,如果要使用只能使用普通成员变量的使用方式

cs 复制代码
class Program
{
    static void Main(string[] args)
    {
     
        Test t = new Test();
        Test t2 = new Test();
        Console.WriteLine(t.testInt);   // ✅ 正确:通过实例访问
        Console.WriteLine(t2.testInt2); // ✅
    }
}

扩展方法

为现有非静态变量类型添加新方法

|-------------------------------------------------------|
| 1.必须把扩展方法定义在静态类中,每个扩展方法也必须声明为静态的 |
| 2.所有扩展方法必须要使用this关键字对第一个参数进行修饰(第一个参数value即调用该扩展方法的对象) |

cs 复制代码
static class Tools
{
    // 为 int 拓展了一个成员方法
    // 成员方法是需要实例化对象后才能使用的
    // value 代表使用该方法的实例化对象

    public static void SpeakValue(this int value)
    {
        Console.WriteLine("唐老师为int拓展的方法" + value);
    }
}

class Program
{
    static void Main(string[] args)
    {
       
        int i = 10;
        int类型的 实例化对象i调用了 int 类型扩展的新方法SpeakValue
        i.SpeakValue();
    }
}

这里int类是系统自带的,系统本身未提供SpeakValue方法给int类型,这里使用扩展方法相当于是int类型扩展了新方法SpeakValue

为自定义类扩展方法

这里就是给Test类(自定义类)扩展了一个方法,然后一个t(Test类实例化对象)调用此方法

cs 复制代码
static class Tools
{
    // 为 int 拓展了一个成员方法
    // 成员方法是需要实例化对象后才能使用的
    // value 代表使用该方法的实例化对象

    public static void Fun3(this Test t)
    {
        Console.WriteLine("为test拓展的方法");
    }
}


static void Main(string[] args)
    {     
        Test t = new Test();
        t.Fun3();
    }

class Test
{
    public int i = 10;

    public void Fun1()
    {
        Console.WriteLine("123");
    }

    public void Fun2()
    {
        Console.WriteLine("456");
    }
}

当扩展方法和类中自带方法重名时

这里优先输出结果是类中自带方法。

cs 复制代码
using System;

internal static class Tools
{
    // 为 Test 拓展一个方法(扩展方法必须定义在 static 类中)
    public static void Fun2(this Test t)
    {
        Console.WriteLine("为test拓展的方法");
    }
}

internal static class Program
{
    private static void Main(string[] args)
    {
        var t = new Test();
        t.Fun2();
    }
}

internal class Test
{
    public void Fun2()
    {
        Console.WriteLine("456");
    }
}

重载运算符

让自定义结构体和自定义类使用运算符

基本语法:

cs 复制代码
public static 返回类型 operator  运算符(参数列表)

operator + 并不是一个"类名",而是一个 C# 中用于定义运算符重载的特殊语法。
它的作用是:告诉编译器,当两个 Point 对象使用 + 运算符时,应该执行这个方法里的逻辑。

算数运算符

cs 复制代码
class Point
{
    public int x;
    public int y;

    public static Point operator +(Point p1, Point p2)
    {
        Point p = new Point();
        p.x = p1.x + p2.x;
        p.y = p1.y + p2.y;
        return p;
    }
}


class Program
{
    static void Main(string[] args)
    {
        Console.WriteLine("运算符重载");
        Point p = new Point();
        p.x = 1;
        p.y = 1;

        Point p2 = new Point();
        p2.x = 2;
        p2.y = 2;

        Point p3 = p + p2;
    }
}

重载的表现

cs 复制代码
class Point
{
    public int x;
    public int y;

    public static Point operator +(Point p1, Point p2)
    {
      ..................
    }

    public static Point operator +(Point p1, int value)
    {
        Point p = new Point();
        p.x = p1.x + value;
        p.y = p1.y + value;
        return p;
    }

    class Program
{
    static void Main(string[] args)
    {
        ......//沿用上方案例p1,p2
        Point p4 = p2 + 3
    }
}
}

其他运算符

cs 复制代码
//还有条件运算符以及逻辑运算符

public static bool operator !(Point p1)
{
    return false;
}

public static bool operator >(Point p1, Point p2)
{
    return false;
}
相关推荐
yaoxin5211232 小时前
294. Java Stream API - 对流进行归约
java·开发语言
ghie90902 小时前
基于MATLAB的演化博弈仿真实现
开发语言·matlab
曹轲恒2 小时前
Thread.sleep() 方法详解
java·开发语言
aini_lovee2 小时前
基于Qt实现CAN通信上位机
开发语言·qt
27669582922 小时前
dy bd-ticket-guard-client-data bd-ticket-guard-ree-public-key 逆向
前端·javascript·python·abogus·bd-ticket·mstoken·ticket-guard
小小仙。2 小时前
IT自学第十九天
java·开发语言
WX-bisheyuange2 小时前
基于SpringBoot的交通管理在线服务系统
前端·javascript·vue.js·毕业设计
一然明月2 小时前
C#语言基础详解和面向对象编程核心概念与高级特性详解(万字详解带示例代码)
开发语言·c#
宵时待雨2 小时前
数据结构(初阶)笔记归纳4:单链表的实现
c语言·开发语言·数据结构·笔记·算法