我的编程空间,编程开发者的网络收藏夹
学习永远不晚

C#中面向对象的相关知识点有哪些

短信预约 -IT技能 免费直播动态提醒
省份

北京

  • 北京
  • 上海
  • 天津
  • 重庆
  • 河北
  • 山东
  • 辽宁
  • 黑龙江
  • 吉林
  • 甘肃
  • 青海
  • 河南
  • 江苏
  • 湖北
  • 湖南
  • 江西
  • 浙江
  • 广东
  • 云南
  • 福建
  • 海南
  • 山西
  • 四川
  • 陕西
  • 贵州
  • 安徽
  • 广西
  • 内蒙
  • 西藏
  • 新疆
  • 宁夏
  • 兵团
手机号立即预约

请填写图片验证码后获取短信验证码

看不清楚,换张图片

免费获取短信验证码

C#中面向对象的相关知识点有哪些

本篇内容介绍了“C#中面向对象的相关知识点有哪些”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!

switch和字典

前文提到过,有个游戏里面有个著名的屎山,就是跑了19亿次if,把玩家憋得不行。而解决这个问题其实非常简单,只需用到switch就可以了。

比如打牌的时候,正常只有2-10是数字,1是A,11是J,12是Q,13是K,如果要用if...else if这种方法来判断,那么遇到K的时候需要判断好多次才行,switch则只需一次

void cardName(int cardNum){    switch (cardNum)    {        case 1: Console.WriteLine("A"); break;        case 11: Console.WriteLine("J"); break;        case 12: Console.WriteLine("Q"); break;        case 13: Console.WriteLine("K"); break;        default: Console.WriteLine(cardNum); break;    }}

C#中的switch语句,除了用break可以跳出switch之外,还可以用goto case xx来跳转到第xx个case,这个特性还挺有意思的,所以在这里多提一嘴,但初学者其实只要有switch case这个概念就可以了。

switch case语句之所以在性能上优于if...else,极有可能是用了哈希表,通过计算输入的方法,来快速链接到执行程序的入口,达到常数级别的时间复杂度。

在C#中,提供了字典这种数据结构,可以实现类似于switch case的效果。所谓字典,就是一组键值对,通过键值的一一对应关系,达到通过键来索引值的目的,其定义方式如下

Dictionary<int, string> card = new Dictionary<int, string>{    {1,"A" },    {11, "J" },    {12, "Q" },    {13, "K" }};

Dictionary为数据类型的名字,<int, string>表示其键为整型,值为字符串。后面的new表示创建新对象,这个在数组的时候就已经学过了,最后花括号中的四行代码,用于对Dictionary进行初始化。

有了这个,就可以更简洁地实现抽牌功能

Console.WriteLine(card[1]);//命令行中显示 A

那么这个时候可能有人问了,那2-10这9张牌咋办?是需要加一个if来判断吗?

答案是当然不用,毕竟字典是一种动态的数据结构,内部元素是可以增长的,只需跑个循环将其填充上就行了

for (int i = 2; i < 11; i++){    card.Add(i, i.ToString());}

其中,card.Add就是添加元素的方法,i.ToString()可以将整型的i转化为字符串。

这样,就有了从A到K的扑克牌。

类、成员、方法

扑克牌除了面值之外,还要看花色的。换言之,用数字是没法完全描述扑克牌的所有属性的。

当然,这种属性其实可以用字典来实现,例如现在有一个红桃K,可以表示为

Dictionary<string, string> 红桃K = new Dictionary<string, string>{    {"花色", "红桃" },    {"数值", "13" },    {"名字", "K" }};

首先,看到红桃K千万不要害怕,在C#中,中文也是可以当作变量名的。

其次,字典毕竟不太方便,因为C#中的字典要求指定数据类型,数值这个键对应的值,按理说应该是整型才比较合理,但无奈之下,只能是字符串。

面对这种痛点,就得看Class来大显身手了。

class Card{    public int Id { get; set; }    public string Name { get; set; }    public string Color { get; set; }}

其中,class表示,Card是一个类,后面的花括号里就是这个类的成员变量。

public表示,这是个公开的属性,可以被别人调用;{get; set;}表示这个属性既可以被调用,也可以被赋值。

需要注意的是,目前我们写下的所有代码,都是在.NET6中所定义的顶级语句。这种顶级语句,并不符合以往C#代码的规范,由此也会导致一些问题,即顶级语句必须写在所有类定义的前面。

所以,如果想创建一个Card类的实例,需要在class Card之前调用,这个很反直觉,但习惯了就好。

Card 红桃A = new Card { Id = 1, Name = "A", Color = "红桃" };

接下来遇到了一个很尴尬的问题,的确是新建了一个红桃A,然后呢?

首先,可以通过.来调用类的属性,例如

Console.WriteLine(红桃A.Name);

其次,可以在类中添加成员方法,然后调用一下

class Card{    public int Id { get; set; }    public string Name { get; set; }    public string Color { get; set; }    public void introduce()    {        Console.WriteLine($"我的名字是{Color}{Name}");    }}

调用仍然要在class Card这行的前面,

红桃A.introduce();

得到的结果为

我的名字是红桃A

是时候规范一下写法了

顶级语句用起来虽然很爽,但,至少在目前看来,最适合的应用场景是算法原理的快速验证,而非做开发。因为开发要涉及到团队合作,涉及到大家按照相同的规范去分块做不同的内容,为了团队和整体的效率,不得不牺牲局部代码的简洁性,所以作为C#程序员,还是要习惯那种类似Java风格的完全的面向对象写法。

重新建一个控制台应用,这次在选择框架的界面,勾选上不使用顶级语句,这回看到的就是这样的一个结果

namespace MySecondCS{    internal class Program    {        static void Main(string[] args)        {            Console.WriteLine("Hello, World!");        }    }}

就是前面提到的,Hello World外面有一层Main函数,Main函数外面有一个class,class外面有一个命名空间。

然后把之前写过的Card类写在Program前面,并将Main函数中的内容改为

static void Main(string[] args){    Card card = new Card() { Id = 1, Name = "A", Color = "红桃" };    card.introduce();}

这样启动命令行,会得到上一节同样的结果。

将类写在一个文件中当然没什么问题,但随着所开发的应用越来越复杂,涉及到的类也会越来越多,全部堆在一个文件中,缺乏有效的组织,显然是不成的。

正所谓晴天带伞、居安思危,全堆一个文件不行,那就把类写在另一个文件中就是了。右键解决方案中的项目名,选择添加类,如下图

C#中面向对象的相关知识点有哪些

类名取为Card,然后项目中除了Program.cs之外,还会出现一个Card.cs,其内容为

namespace MySecondCS{    internal class Card    {    }}

其中,namespace为命名空间,在同一个命名空间中的类可以互相调用。internal是一个用于修饰类的关键字,是对可访问性的一种限制,这个限制并不强,只要在一个程序集中,就可以访问。

这种访问限制,在前面第一次创建Card的时候就有提过,Card类中,修饰成员变量用到的public也是用于访问限制的。

接下来把之前写好的Card代码剪切进internal class Card中,在启动命令行,程序仍然是可以跑通的。

继承

之所以要有继承这个概念,是因为纸牌的玩法太多了,比如我小的时候就喜欢搜集小当家的水浒卡,梁山好汉108将刚好是两幅扑克牌,但是Card类中并没有额外给梁山好汉提供位置。

这个时候就会遇到两难问题,若直接把Card改成小当家水浒卡,那么打牌的人会觉得这玩意没啥用,只会白白地浪费内存;若是另起炉灶重新写一个类,那老板会觉得你同样的内容写两遍,是不是欺负我不懂技术?然后说不定就扣工资了。

所以,继承就比较好地解决了这个问题,就像这个名字暗示的,在C#中,可以新建一个水浒卡的类,可以在继承Card类中的各种成员之外,添加自己独有的成员。

接下来在Card类的下面,新建一个类,就叫UniCard,表示统一小当家水浒卡,如下所示

class UniCard : Card{    public int Order { get; set; }    public string PersonName { get; set; }}

其中,UniCard : Card就表示,前者是对后者的继承,所有在Card中public的功能,都可以在UniCard中无痛调用。

接下来在UniCard中实现一个功能,即根据排名确定其对应的纸牌面额。纸牌大小排序是大小王,然后是AkQJ,再然后是10到2。

那么2副扑克牌中,有4个大小王,其他诸如AKQJ之类的都有8张。现令大小王是0,A是1,那么其对应的排序就是0->1->13->12->...->2。

也就是说,排名1, 2, 3, 4对应扑克牌中的大小王,面额为0;5-12对应扑克牌中的A,面额为1,然后接下来,每新增八位,其面额就加1。其函数实现为

int order2Id(uint order){    if(order <= 4)        return 0;    else if (order <= 12)        return 1;    else        return 14 - (order-4) / 8;}

这个函数是非常简单的,但接下来要将其嵌入到UniCard类中,实现通过Order自动生成Id这样的功能

class UniCard : Card{    public int Order { get; set; }    public string PersonName { get; set; }    public void getIdName()    {        if (this.Order <= 4)            this.Id = 0;        else if (this.Order <= 12)            this.Id = 1;        else            this.Id = 14 - (this.Order - 4) / 8;        switch (this.Id)        {            case 0: this.Name = "Joker"; break;            case 1:this.Name = "A"; break;            case 13:this.Name = "K"; break;            case 12:this.Name = "Q";break;            case 11:this.Name = "J"; break;            default: this.Name = this.Id.ToString(); break;        }    }}

其中,this表示当前的这个class,在不引起歧义的情况下是可以省略的。所谓引起歧义,就是假如这个class外面已经有了一个Name,那么在这个class里面如果非常突兀地来一个Name=1,可能会导致程序不知道这个Name到底指向谁。

另外,如果if后面跟着的程序块中只有一行代码,那么花括号可以省略。

除此之外,上面的代码稍微长了一点,但并没有新的知识点,只是相当于复习了一下switch case。

接下来,在Main函数中创建一个UniCard,并调用其继承的自我介绍的函数。

static void Main(string[] args){    UniCard uniCard = new UniCard();    uniCard.Order = 6;    uniCard.Color = "红桃";    uniCard.getIdName();    uniCard.introduce();}

运行之后,命令行输出我的名字是红桃A

6号如果我没记错的话,是豹子头林冲,结果现在变成了红桃A,看来这个继承还是比较成功的。

枚举

扑克牌的花色只有四种,红桃、黑桃、草花、方片,如果把数据类型限制为字符串,保不准有人会把牌的花色定义为“五彩斑斓黑”之类的,为了做一个限制,目前想到比较好的方案是用字典

Dictionary<int, String> CARD_COLOR = new Dictionary<int, string>{    {0, "黑桃" },    {1, "红桃" },    {2, "草花" },    {3, "方片" }};

然后再把花色定义为整型,想要看花色的时候以CARD_COLOR[0]这种形式调用。

这样一来思路就打开了,甚至可以将花色封装成字符串数组

String[] CARD_COLOR = new string[] { "黑桃", "红桃", "草花", "方片" };

然而在C#中,其实有更加优雅的解决方案,这个方案就是枚举

public enum COLOR { 黑桃, 红桃, 草花, 方片};

上面这行代码可以写在internal class Card的外面,然后在Card类中可以把花色定义为

public COLOR Color { get; set; }

枚举这种数据类型的好处是,既有字符串的特点,又有整型的特点,以COLOR这种类型为例,黑桃对应的是0,红桃对应的是1,以此类推。

这样一来,getIdName这个函数,除了可以通过排名来算牌的面额,还可以据此计算牌的花色。

public void getIdName(){    //...    //写在switch case后面    if (this.Order <= 2)        this.Color = COLOR.黑桃;    else if (this.Order <= 4)        this.Color = COLOR.红桃;    else        this.Color = (COLOR)((this.Order - 5) % 8 / 2);}

其中COLOR.黑桃是常用的枚举类型的调用方法,而后面的(COLOR)相当于把其后面的(this.Order - 5) % 8 / 2这个整数,强制转化为枚举类型。

改完这些之后,就会发现Main函数中的uniCard.Color = "红桃";出现了红色的下划波浪线,说明出现了错误。原因也很简单,现在的Color是枚举类型,并不能赋值一个字符串。

将这行删掉之后,再运行程序,命令行输出为

我的名字是黑桃A

说明introduce中的$"我的名字是{Color}{Name}"仍然发生了作用,枚举类型,通过6 66这个数值,计算得到了COLOR.黑桃这个结果,最后又通过$字符串转化成了字符串。

这就是前文所言,枚举类型,既有整型,又有字符串。

构造函数和方法重载

现在回顾一下Main函数,发现UniCard的创建过程未免太过繁琐。

static void Main(string[] args){    UniCard uniCard = new UniCard();    uniCard.Order = 6;    uniCard.getIdName();    uniCard.introduce();}

Main函数中的4行代码中,如果只保留第一行和最后一行,那就完美了,比如写成这种

UniCard uniCard = UniCard(6);uniCard.introduce();

在这个过程中,UniCard变成了一个函数,通过输入一个排名,便可以初始化花色、牌额等内容,这个函数就叫做构造函数,想要实现,只需在UniCard中添加

public UniCard(int order){    Order = order;    getIdName();}

需要注意,在Order=order中,前面的Order为类成员,其实可以写为this.Order,getIdName也可以写为this.getIdName,由于不会引起歧义,所以将this省略了。

这时会发现,Main函数中又出现了错误:

UniCard uniCard = new UniCard();

这时因为,我们已经为UniCard设定了唯一的构造函数,这个构造函数必须要输入一个整型才能执行,UniCard()的参数却空空如也,这不报错才怪,解决方法也很简单,只需将其改为我们喜闻乐见的形式就行了

static void Main(string[] args){    UniCard uniCard = new UniCard(6);    uniCard.introduce();}

这个时候有人说了,那我就想生成一个啥也没有的UniCard,你这么改来改去把我想要的改没了,你还我UniCard()。

这个需求也是可以满足的,这就是所谓的重载。所谓重载,就是在C#中,允许创建一些同名函数,这些同名函数可以有着不同的输入参数,所以只需在public UniCard(int order)前面或者后面添加下面的代码,就可以既满足带参数的构造函数,又满足不带参数的构造函数了。

public UniCard(){}

运算符重载

无论是是打牌,还是梁山好汉,都是有排名的。有排名就可以比大小,比大小,就涉及到了大于号等于号小于号之类的东西。

正如字符串可以把加号更改为拼接的意思,Card也应该有重新定义运算符的能力,这种能力就叫做运算符重载。

对于已经建立起函数重载这种概念的人来说,运算符重载并不存在理解上的困难,毕竟运算符也是一种函数。

下面针对UniCard这种数据类型,对比较运算符进行重载,

public static bool operator< (UniCard a, UniCard b){    return a.Order > b.Order;}public static bool operator>(UniCard a, UniCard b){    return a.Order < b.Order;}public static bool operator==(UniCard a, UniCard b){    return a.Order == b.Order;}public static bool operator!=(UniCard a, UniCard b){    return a.Order != b.Order;}

非常直观,其中static为静态类的修饰符,所谓静态类型,表示在类尚未实例化时就可以调用,所有运算符重载函数都必须是static的。

operator<表示重新定义运算符<,bool类型标识作为运算结果的数据类型。

在这种排名中,肯定是数越小的人地位越高,所以排名第一大于排名第5,从而其Order大的反而小。

在进行了这些运算符重载之后,就可以在Main函数中进行调用了

static void Main(string[] args){    UniCard a = new UniCard(15);    UniCard b = new UniCard(25);    if (a > b)        Console.WriteLine($"{a.Color}{a.Name} > {b.Color}{b.Name}");    else        Console.WriteLine($"{a.Color}{a.Name} <= {b.Color}{b.Name}");}

运行之后,命令行输出为

红桃K > 草花Q

“C#中面向对象的相关知识点有哪些”的内容就介绍到这里了,感谢大家的阅读。如果想了解更多行业相关的知识可以关注编程网网站,小编将为大家输出更多高质量的实用文章!

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

C#中面向对象的相关知识点有哪些

下载Word文档到电脑,方便收藏和打印~

下载Word文档

猜你喜欢

C#中面向对象的相关知识点有哪些

本篇内容介绍了“C#中面向对象的相关知识点有哪些”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!switch和字典前文提到过,有个游戏里面有个
2023-07-05

Python面向对象知识点有哪些

今天就跟大家聊聊有关Python面向对象知识点有哪些,可能很多人都不太了解,为了让大家更加了解,小编给大家总结了以下内容,希望大家根据这篇文章可以有所收获。类: 用来描述具有相同的属性和方法的对象的集合。它定义了该集合中每个对象所共有的属性
2023-06-17

python--初始面向对象:类的相关知识,对象的相关知识

引子假设你是一个开发人员,现在需要你开发一款叫做当然很简单,两个角色,1个人物,1个boss,且人物和boss都有不同的技能,比如人物用觉醒技能秒了boss,掉了xx装备,boss用大招秒了人物,人物死亡,怎么描述这种不同的人物和他们的功能
2023-01-30

Java中类与对象的相关知识点有哪些

这篇文章给大家介绍Java中类与对象的相关知识点有哪些,内容非常详细,感兴趣的小伙伴们可以参考借鉴,希望对大家能有所帮助。一、面向过程与面向对象的理解C语言是面向过程的,关注的是过程,分析出求解问题的步骤,通过函数调用逐步解决问题。JAVA
2023-06-25

javascript面向对象编程的知识点有哪些

这篇文章主要介绍了javascript面向对象编程的知识点有哪些的相关知识,内容详细易懂,操作简单快捷,具有一定借鉴价值,相信大家阅读完这篇javascript面向对象编程的知识点有哪些文章都会有所收获,下面我们一起来看看吧。函数的定义和使
2023-06-29

一文带你吃透C#中面向对象的相关知识

这篇文章主要为大家详细介绍了C#中面向对象的相关知识,文中的示例代码讲解详细,对我们学习C#有一定的帮助,需要的小伙伴可以参考一下
2023-02-26

JAVA 面向对象之多态的知识点有哪些

本篇内容介绍了“JAVA 面向对象之多态的知识点有哪些”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!1. 概念多态是面向对象程序设计(OOP
2023-07-02

React的相关知识点有哪些

这篇文章主要介绍“React的相关知识点有哪些”的相关知识,小编通过实际案例向大家展示操作过程,操作方法简单快捷,实用性强,希望这篇“React的相关知识点有哪些”文章能帮助大家解决问题。React与传统MVC的关系轻量级的视图层库!A J
2023-06-03

KeyDB的相关知识点有哪些

今天小编给大家分享一下KeyDB的相关知识点有哪些的相关知识点,内容详细,逻辑清晰,相信大部分人都还太了解这方面的知识,所以分享这篇文章给大家参考一下,希望大家阅读完这篇文章后有所收获,下面我们一起来了解一下吧。线程模型KeyDB将redi
2023-06-19

有哪些Java的相关知识点

这篇文章主要介绍“有哪些Java的相关知识点”,在日常操作中,相信很多人在有哪些Java的相关知识点问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”有哪些Java的相关知识点”的疑惑有所帮助!接下来,请跟着小编
2023-06-16

Git的相关知识点有哪些

这篇文章主要介绍“Git的相关知识点有哪些”的相关知识,小编通过实际案例向大家展示操作过程,操作方法简单快捷,实用性强,希望这篇“Git的相关知识点有哪些”文章能帮助大家解决问题。分支和合并Git 跟其他版本控制系统***的优势就在于其高级
2023-06-17

Java中Volatile相关知识点有哪些

这篇文章主要介绍“Java中Volatile相关知识点有哪些”,在日常操作中,相信很多人在Java中Volatile相关知识点有哪些问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”Java中Volatile相关
2023-06-16

C语言指针的相关知识点有哪些

这篇文章将为大家详细讲解有关C语言指针的相关知识点有哪些,小编觉得挺实用的,因此分享给大家做个参考,希望大家阅读完这篇文章后可以有所收获。第一站 字符指针----存放字符地址的指针1.使用方法(1)直接使用字符int main(){
2023-06-29

Java对象的知识点有哪些

这篇文章主要讲解了“Java对象的知识点有哪些”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“Java对象的知识点有哪些”吧!1、问题的复杂性直接取决于抽象的类型和质量,同一个问题,如果抽象的
2023-06-03

编程热搜

  • Python 学习之路 - Python
    一、安装Python34Windows在Python官网(https://www.python.org/downloads/)下载安装包并安装。Python的默认安装路径是:C:\Python34配置环境变量:【右键计算机】--》【属性】-
    Python 学习之路 - Python
  • chatgpt的中文全称是什么
    chatgpt的中文全称是生成型预训练变换模型。ChatGPT是什么ChatGPT是美国人工智能研究实验室OpenAI开发的一种全新聊天机器人模型,它能够通过学习和理解人类的语言来进行对话,还能根据聊天的上下文进行互动,并协助人类完成一系列
    chatgpt的中文全称是什么
  • C/C++中extern函数使用详解
  • C/C++可变参数的使用
    可变参数的使用方法远远不止以下几种,不过在C,C++中使用可变参数时要小心,在使用printf()等函数时传入的参数个数一定不能比前面的格式化字符串中的’%’符号个数少,否则会产生访问越界,运气不好的话还会导致程序崩溃
    C/C++可变参数的使用
  • css样式文件该放在哪里
  • php中数组下标必须是连续的吗
  • Python 3 教程
    Python 3 教程 Python 的 3.0 版本,常被称为 Python 3000,或简称 Py3k。相对于 Python 的早期版本,这是一个较大的升级。为了不带入过多的累赘,Python 3.0 在设计的时候没有考虑向下兼容。 Python
    Python 3 教程
  • Python pip包管理
    一、前言    在Python中, 安装第三方模块是通过 setuptools 这个工具完成的。 Python有两个封装了 setuptools的包管理工具: easy_install  和  pip , 目前官方推荐使用 pip。    
    Python pip包管理
  • ubuntu如何重新编译内核
  • 改善Java代码之慎用java动态编译

目录