使用 C# 学习面向对象编程:第 4 部分

C# 构造函数

第 1 部分仅介绍了类构造函数的基础知识。 在本课中,我们将详细讨论各种类型的构造函数。

属性类型

  • 默认构造函数
  • 构造函数重载
  • 私有构造函数
  • 构造函数链
  • 静态构造函数
  • 析构函数

请注意构造函数的一些基本概念,并确保你的理解非常清楚,否则你无法理解 OOP(构造函数)。

  1. 构造函数的名称与类名相同。
  2. 构造函数的目的是为了初始化成员变量。
  3. 创建对象时会自动调用构造函数。
  4. 构造函数没有任何返回类型,甚至没有 void。
  5. 如果我们希望自动执行某些代码,那么我们想要执行的代码必须放在构造函数中。
  6. 我们不能明确调用构造函数。

C# 构造函数的一般形式如下。

modifier constructor_name(parameters)
{
    // constructor body
}

修饰符可以是 private、public、protected 或 internal。构造函数的名称必须是其定义所属类的名称。构造函数可以接受零个或多个参数。零个参数(即无参数)的构造函数称为默认构造函数。请记住,构造函数没有返回类型。

默认构造函数

无参数的构造函数称为默认构造函数。请记住,构造函数没有返回类型。默认构造函数只是调用直接基类的无参数构造函数。

例子

using System;

namespace DefaultConstructors
{
    class Program
    {
        static void Main(string[] args)
        {
            // 创建 car 类的一个实例 sportscar,调用默认构造函数
            car sportscar = new car();

            // 打印 sportscar 的 model_Id 属性值
            Console.WriteLine("Car Model is :{0} ", sportscar.model_Id);

            // 打印 sportscar 的 Maker_Name 属性值
            Console.WriteLine("Car Name is :{0}", sportscar.Maker_Name);

            // 等待用户按下任意键继续执行程序
            Console.ReadKey();
        }

        // 定义 car 类
        class car
        {
            // 私有字段 model,表示车型
            private int model = -1;

            // 私有字段 maker,表示制造商
            private string maker = string.Empty;

            // 默认构造函数
            public car()
            {
                // 默认构造函数的主体是空的,可以添加初始化逻辑
            }

            // 公共只读属性 model_Id,用于获取 model 字段的值
            public int model_Id
            {
                get 
                {
                    return model;
                }
            }

            // 公共只读属性 Maker_Name,用于获取 maker 字段的值
            public string Maker_Name
            {
                get
                {
                    return maker;
                }
            }
        }
    }
}

输出


在这个简单的例子中,我们有一个无参数或零参数的构造函数,它是类的默认构造函数。上述示例的输出是空成员变量。

请注意另外一点;如果我们从示例 1 中删除以下代码,则输出是相同的。

public car()
{
   //Default Constructor
}

这意味着如果我们没有定义类的构造函数,系统将调用默认构造函数。

构造函数重载

首先,我们来讨论一下构造函数重载的目的;对前面的主题有清晰的理解非常重要。在设计 OOP 模型时存在许多复杂的情况,我们需要为类的不同目的初始化一组不同的成员变量。所以我们需要使用构造函数重载。构造函数重载的定义是。

和成员函数一样,构造函数也可以在类中重载。重载的构造函数必须在参数数量和/或参数类型和/或参数顺序上有所不同。

例子

using System;

namespace ConstructorsOverloading
{
    class Program
    {
        static void Main(string[] args)
        {
            // 使用无参数构造函数创建 car 类的一个实例
            car sportscar1 = new car();

            // 使用包含两个参数(model 和 maker)的构造函数创建 car 类的一个实例
            car sportscar2 = new car(2013, "mercedes");

            // 使用包含两个参数(maker 和 Enginetype)的构造函数创建 car 类的一个实例
            car sportscar3 = new car("mercedes", 7.8);

            // 输出使用无参数构造函数创建的 sportscar1 的属性值
            Console.WriteLine("Constructor without arguments");
            Console.WriteLine("Car Model is :{0} ", sportscar1.model_Id);
            Console.WriteLine("Car Name is :{0}", sportscar1.Maker_Name);
            Console.WriteLine("Car Engine Power is :{0}", sportscar1.Engine);

            // 输出使用包含两个参数的构造函数创建的 sportscar2 的属性值
            Console.WriteLine("\nConstructor with two arguments");
            Console.WriteLine("Car Model is :{0} ", sportscar2.model_Id);
            Console.WriteLine("Car Name is :{0}", sportscar2.Maker_Name);
            Console.WriteLine("Car Engine Power is :{0}", sportscar2.Engine);

            // 输出使用包含两个参数的构造函数创建的 sportscar3 的属性值
            Console.WriteLine("\nConstructor with two arguments");
            Console.WriteLine("Car Model is :{0} ", sportscar3.model_Id);
            Console.WriteLine("Car Name is :{0} ", sportscar3.Maker_Name);
            Console.WriteLine("Car Engine Power is :{0}", sportscar3.Engine);

            // 等待用户按下任意键继续执行程序
            Console.ReadKey();
        }

        // 定义 car 类
        class car
        {
            // 私有字段,表示车型
            private int model = -1;

            // 私有字段,表示制造商
            private string maker = string.Empty;

            // 私有字段,表示发动机类型
            private double Enginetype = 0.0;

            // 无参数的默认构造函数
            public car()
            {
                // 默认构造函数的主体是空的,可以添加初始化逻辑
            }

            // 包含两个参数(model 和 maker)的构造函数
            public car(int _model, string _maker)
            {
                model = _model;
                maker = _maker;
            }

            // 包含两个参数(maker 和 Enginetype)的构造函数
            public car(string _maker, double _power)
            {
                maker = _maker;
                Enginetype = _power;
            }

            // 公共属性,用于获取和设置 model 字段的值
            public int model_Id
            {
                get
                {
                    return model;
                }
                set
                {
                    model = value;
                }
            }

            // 公共属性,用于获取和设置 maker 字段的值
            public string Maker_Name
            {
                get
                {
                    return maker;
                }
                set
                {
                    maker = value;
                }
            }

            // 公共属性,用于获取和设置 Enginetype 字段的值
            public double Engine
            {
                get
                {
                    return Enginetype;
                }
                set
                {
                    Enginetype = value;
                }
            }
        }
    }
}

输出


亲爱的读者,请注意,在这个例子中,我们使用三个不同的对象重载了构造函数,它们是sportscar1、sportscar2 和 sportscar3。

我们注意到

  • sportscar1 没有参数(默认构造函数超出了主题范围)。因此该成员变量具有在初始化时分配的默认值。
  • sportscar2 有两个参数,分别用值 2013 和 Mercedes 初始化成员变量 model 和 name,但没有初始化 Enginetype 变量,因此它具有默认值零。
  • sportscar3 有两个参数,分别用值 Mercedes 和 7.8 初始化成员变量 name 和 Enginetype,但不初始化 model 变量,因此它具有默认值 -1。

私有构造函数

亲爱的读者,我们知道,私有访问修饰符有点特殊。我们既不能创建类的对象,也不能仅使用私有构造函数来继承类。但是,是的,我们可以在类中拥有一组公共构造函数以及私有构造函数,并且公共构造函数可以通过构造函数链从类内部访问私有构造函数。私有构造函数通常用于仅包含静态成员的类中。

using System;

namespace PrivateConstructors
{
    class Program
    {
        static void Main(string[] args)
        {
            // 使用包含 model 参数的构造函数创建 car 类的一个实例
            car sportscar = new car(2013);
            Console.Read();
        }

        class car
        {
            // 公共字段,表示汽车名称
            public string carname;

            // 私有的默认构造函数
            private car()
            {
                // 初始化 carname 字段
                carname = "lamborghini";
            }

            // 公共的构造函数,包含一个 int 型的 model 参数
            // 该构造函数通过 :this() 调用私有的默认构造函数
            public car(int model) : this()
            {
                // 打印车型年份
                Console.WriteLine("Model Year:{0}", model);

                // 打印制造商名称
                Console.WriteLine("Maker Name:{0}", carname);
            }
        }
    }
}

这是一个非常简单的私有构造函数的例子,其中我们使用公共构造函数来调用私有构造函数。

构造函数链

亲爱的读者,当一个构造函数调用同一个类或该类的基类中的另一个构造函数时,这被称为构造函数链。这是避免代码重复的非常有用的技术。

using System;

namespace Constructorchaining
{
    class Program
    {
        static void Main(string[] args)
        {
            // 使用包含 engine 参数的构造函数创建 car 类的一个实例
            car sportscar = new car(7.8);
            Console.Read();
        }

        class car
        {
            // 公共字段,表示汽车名称
            public string carname;

            // 公共字段,表示车型年份
            public int model;

            // 公共字段,表示发动机类型
            public double engine;

            // 包含一个 carname 参数的构造函数
            public car(string _carname)
            {
                carname = _carname;
            }

            // 包含一个 model 参数的构造函数,并调用包含 carname 参数的构造函数
            public car(int _model) : this("lamborghini")
            {
                model = _model;
            }

            // 包含一个 engine 参数的构造函数,并调用包含 model 参数的构造函数
            public car(double _engine) : this(2013)
            {
                engine = _engine;
                
                // 打印车型年份
                Console.WriteLine("Model Year:{0}", model);
                
                // 打印制造商名称
                Console.WriteLine("Maker Name:{0}", carname);
                
                // 打印发动机类型
                Console.WriteLine("Engine Type:{0}", engine);
            }
        }
    }
}

在前面的例子中,我们创建了三个不同的类,它们都具有相同的名称 car 和不同的参数类型,每个类都链接前一个类来调用另一个构造函数。

静态构造函数

静态构造函数是一种特殊类型,不采用访问修饰符,也不具有参数。在创建第一个实例或引用任何静态成员之前,会自动调用它以初始化类。静态构造函数不会被直接调用。用户无法控制静态构造函数的执行。

using System;

namespace staticconstructors
{
    class Program
    {
        // 定义 car 类
        public class car
        {
            // 静态构造函数
            static car()
            {
                // 打印静态信息,静态构造函数在类第一次被使用前自动调用,并且只调用一次
                System.Console.WriteLine(@"Lamborghini is the best sports car owned by Audi AG 1998 (its static info)");
            }

            // 静态方法 Drive
            public static void Drive()
            {
                // 打印稳定公司信息
                System.Console.WriteLine("Audi is the stable company");
            }
        }

        // 主程序入口点
        static void Main()
        {
            // 调用 car 类的静态方法 Drive
            car.Drive();

            // 再次调用 car 类的静态方法 Drive
            car.Drive();

            // 等待用户按下任意键继续执行程序
            Console.ReadKey();
        }
    }
}

输出


注意,静态构造函数在第一次加载类时被调用。当我们再次调用“car.Drive”时,它不会调用静态构造函数。

析构函数

亲爱的读者,当我们使用 OOP 并在系统内存中创建对象时,需要从系统内存中清除不需要的对象。.NET 框架内置了垃圾收集功能,用于释放未使用对象占用的内存。析构函数是一个与类名同名但以字符 ~ 开头的函数。析构函数不能有任何修饰符 private、public 等。

例子

class car
{
    // 公共构造函数
    public car()
    {
        // 构造函数,在创建对象实例时调用
        // 可以在这里进行对象的初始化操作
        // 比如分配资源,设置初始状态等
    }

    // 析构函数
    ~car()
    {
        // 析构函数,在对象被垃圾回收时调用
        // 可以在这里进行对象的清理操作
        // 比如释放资源,关闭文件,断开网络连接等
    }
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/697938.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

西门子PLC位逻辑指令学习(SCL语言)

R_TRIG 参数 功能 当CLK信号出现一个低电平到高电平的跳变时,输出Q导通一个周期。 实例 定义以下类型变量 "R_TRIG_DB"(CLK:"data".source,Q>"data".result); //当source输入出现低电平到高电平跳变,result信号…

《Brave New Words 》4.2 AI 与学生心理健康辅导的结合

Part IV Better Together 第四部分 携手共进 AI Meets Student Mental Health Coaching AI 与学生心理健康辅导的结合 Here’s the scenario: You’re minutes away from taking a final exam. You’ve studied, but your heart is racing and your mind has gone blank. Anxie…

MIPI A-PHY协议学习

一、说明 A-PHY是一种高带宽串行传输技术,主要为了减少传输线并实现长距离传输的目的,比较适用于汽车。同时,A-PHY兼容摄像头的CSI协议和显示的DSI协议。其主要特征: 长距离传输,高达15m和4个线内连接器; 高速率,支持2Gbps~16Gbps; 支持多种车载线缆(同轴线、屏蔽差分…

探索C++ STL的设计方式:将算法与数据结构分离

STL的设计 一、简介二、STL容器三、C数组四、用户定义的集合4.1、使用标准集合的typedef4.2、重用标准迭代器4.3、实现自己的迭代器 五、总结 一、简介 本文介绍STL的设计方式,以及如何设计自己的组件,使其能够充分利用STL的功能。 STL的设计旨在将算法…

多目标融合参数搜索

多目标融合 权重分类目人群。 trick normlize 不同Score之间含义、量级和分布差异较大:评分计算的不同部分的意义、范围和分布存在显著差异,这使得直接比较或融合它们的结果变得困难。显式反馈(如点赞率)存在用户间差异&#…

盘点四家企业软件巨头的Gen AI应用进程

文/明道云创始人任向晖 目前大部份行业分析还聚焦在Open AI,Langchain这些和Generative AI直接相关的企业和产品上。实际上,企业软件市场的感知和行动已经非常迅速。在此项技术进入公众视野18个月后,我们来盘点一下领先的企业软件应用是如何利…

Lua连接Redis客户端执行命令

该示例演示使用Redis连接池,及Redis执行命令与获取返回数据 require("api.website") local dkjson require("api.dkjson")-- 创建连接池 local pool redis_pool.new() -- 置连接池信息 pool:start("127.0.0.1",6379,"998866&…

C语言之argc、argv与main函数的传参

一 :谁给main函数传参 (1)调用main函数所在的程序的它的父进程给main函数传参,并且接收main函数的返回值 二 :为什么需要给main函数传参 (1)首先mian函数不传承是可以的,也就是说它的…

字符串拼接之char实现

目录 一、前言 二、memcpy函数用法 三、代码实现 一、前言 c中想到字符串拼接,我们都知道可以用c库中std::string的字符串中的简单加法进行拼接。示例: int main() {std::string str1 "hello";std::string str2 "World";std::…

OpenEuler系统学习

OpenEuler系统简介 什么是OpenEuler,个人理解就是:通过社区合作,打造统一和开放的操作系统。 官方是这么介绍的: 欧拉是数字基础设施的开源操作系统,可广泛部署于服务器、云计算、边缘计算、嵌入式等各种形态设备&a…

Vue 面试通杀秘籍

理论篇: 1. 说说对 Vue 渐进式框架的理解(腾讯医典) a) 渐进式的含义: 主张最少, 没有多做职责之外的事 b) Vue 有些方面是不如 React,不如 Angular.但它是渐进的,没有强主张, 你可以在原有…

Kimichat使用案例013:用kimichat批量识别出图片版PDF文件中的文字内容

文章目录 一、介绍二、具体操作三、信息识别一、介绍 图片版的PDF文件,怎么才能借助AI工具来提取其中全部的文字内容呢? 第一步:将PDF文件转换成图片格式 具体方法参见文章: Kimichat使用案例011:用kimichat将PDF自动批量分割成多个图片(零代码编程) 第二步:识别图片中…

Redis实战宝典:基础知识、实战技巧、应用场景及最佳实践全攻略

背景 在Java系统实现过程中,我们不可避免地会借助大量开源功能组件。然而,这些组件往往功能丰富且体系庞大,官方文档常常详尽至数百页。而在实际项目中,我们可能仅需使用其中的一小部分功能,这就造成了一个挑战&#…

重庆地区媒体宣传邀约资源整理

传媒如春雨,润物细无声,大家好,我是51媒体网胡老师。 重庆地区媒体宣传邀约资源整理 一、主流媒体资源 电视台:重庆电视台:作为重庆地区最具影响力的电视媒体之一,拥有多个频道,涵盖新闻、综艺…

第2章 Rust初体验1/8:prelude:简化代码的自动标准库加载:猜骰子冷热游戏

讲动人的故事,写懂人的代码 在跑过Hello world程序后,三个人觉得这样还不过瘾,于是决定把那本Rust书里的猜数字游戏换个新面孔,变成“猜骰子冷热”游戏,然后一起动手实现一下。这样我们就能更深入地体验到Rust编程的乐趣啦。 (顺便说一句,如果你想找这本书的所有代码,…

Sklearn的安装和用法

安装sklearn相对简单,因为它是一个Python库,可以通过Python的包管理器pip来安装。 Windows、macOS和Linux通用步骤: 确保Python已安装: sklearn是基于Python的,所以首先确保你的计算机上安装了Python。推荐使用Pytho…

【图论应用】使用多路图(multigraph)对上海地铁站点图建模,并解决最短路径问题

文章目录 1 前言2 导包导入数据集3 创建多路图,导入节点和边信息3 绘制线路图4 计算最短路径 1 前言 最近正在学习图神经网络,先pick up了一些最基础的图论知识并学习了一些好玩的应用。 本文启发于B站视频(BV1LY411R7HJ)&#…

第1期JAVA社招面试经验月报

面经哥专注互联网社招面试经验分享,关注我,每日推送精选面经,面试前,先找面经哥|面经哥整理了上月30篇面试经历,选取了较为热点高频的面试题供大家参考 基础知识类‍‍‍‍‍ 1、说下双亲委派原则以及类加…

HDFS 读写数据流程

优质博文:IT-BLOG-CN 一、HDFS 写数据流程 HDFS 文件写入流程图如下:三个模块(客户端、NameNode、DataNode) 【1】校验: 客户端通过 DistributedFileSystem 模块向 NameNode 请求上传文件,NameNode 会检…

使用手机做PC机摄像头

准备工作: 带摄像头的安卓手机一部模拟相机软件:Iriun 、DroidCam 、IP摄像头pythonopencv 一、Iriun 1、分别在PC和手机上安装 2、手机和PC在同一个局域网 3、分别打开PC和手机端软件,电脑端就可以使用手机相机 ​ 二、 DroidCam 1、…