首页 > 编程语言 >C#_继承_多态_抽象类_虚方法_密封类_静态类

C#_继承_多态_抽象类_虚方法_密封类_静态类

时间:2024-03-22 14:30:19浏览次数:21  
标签:Console C# 多态 System WriteLine new using 抽象类 public

文章目录

前言

C#是面向对象的编程语言,面向对象编程的四项基本原则:

  • 抽象:将实体的相关特性和交互建模为类,以定义系统的抽象表示

  • 封装:隐藏对象的内部状态和功能,并仅允许通过一组公共函数进行访问

  • 继承:根据现有抽象创建新抽象的能力

  • 多形性(多态):跨多个抽象以不同方式实现继承属性或方法的能力

类的继承

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace _01_类的继承
{
    internal class Program
    {
        static void Main(string[] args)
        {
            //继承:根据现有的类,生成一个新的类
            //当创建一个类的时候,可以不需要重新编写新的成员和方法,而是继承自现有的类,
            这个被继承类我们称之为"父类"(基类),这个新的类我们称之为"子类"(派生类)
            //如果一个类没有继承自任何类,那么默认他继承object,C#中所有类,
            都直接或者间接继承自 object,object是所有类的"终极基类"

            Student student = new Student()
            {
                Name = "Test",
                Age = 18,
                StudentId = "20240321",
                Schoole = "爱疯学校"
            };
            student.Eat();
            student.Study();

            SamllStudetn samllStudetn = new SamllStudetn() { Name = "小学生", StudentId = "1232132" };
            samllStudetn.Cry();


            //任意类型的数据,都可以赋值给object类型的变量
            object aa = 10;

            //一个类的实例化对象,可以被赋值给他的父类型
            object s1 = new SamllStudetn();
            Student s2 = new SamllStudetn();
            People s3 = new SamllStudetn();
        }
    }
    //基类
    class People
    {
        public string Name { get; set; }
        public int Age { get; set; }
        public char Sex { get; set; }
        public void Eat()
        {
            Console.WriteLine("吃饭");
        }
    }
    //派生类
    //在定义一个类的时候  使用 ":" 基类  实现继承
    //当一个类继承自另一个类的时候,子类将自动拥有父类的成员(成员变量和成员方法)
    class Student : People
    {
        public string StudentId { get; set; }
        public string Schoole { get; set; }

        public void Study()
        {
            Console.WriteLine($"我是{Name},在{Schoole}学习");
        }
    }

    //基类和派生类并不是绝对的一个概念,是相对的,一个类可以同时是基类和派生类
    class SamllStudetn : Student
    {
        public void Cry()
        {
            Console.WriteLine("背着炸药包,我要炸学校");
        }
    }
}

继承类的构造函数

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace _02_继承类的构造函数
{
    internal class Program
    {
        static void Main(string[] args)
        {

            Man man = new Man();
            Console.WriteLine(man.IQ);
            Console.WriteLine(man.Sex);
            Console.WriteLine(man.Name);
        }
    }
    class People
    {
        public string Name { get; set; }
        public char Sex { get; set; }
        public readonly int IQ;
        private Random r = new Random();
        public People(){
            Console.WriteLine("1.People的构造函数");
            IQ=r.Next(0,250);
            Name = "吴凡";
        }
    }
    class Man : People
    {
        //当new一个类的时候,这个子类创建之前父类就应该先存在,因此会先执行
        父类的构造函数进行父类的创建,然后在执行子类的构造函数
        public Man()
        {
            Console.WriteLine("2.Man的构造函数");
            Sex = '男';
        }
        //子类中直接操作定义在父类的属性和字段
        public void Fn()
        {
            Name = "罗祥";
        }
    }
}

子类访问父类

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace _03_子类访问父类
{
    internal class Program
    {
        static void Main(string[] args)
        {
            //
            //new People();
            //new People("吴凡",'男');
            Man man1 = new Man();
            Console.WriteLine(man1.Name);
            Console.WriteLine(man1.Sex);
            Man man2 = new Man("刘凡");
            Console.WriteLine(man2.Name);
            Console.WriteLine(man2.Sex);
        }
    }

    class People
    {
        public string Name { get; set; }
        public char Sex { get; set; }
        //类里面可以拥有多个同名的但是不同参数的方法,当调用方法的时候,
        会自动根据方法传递的参数,选择不同的方法执行(方法(函数)重载)
        public People()
        {
            Console.WriteLine("People的无参构造函数");
        }
        public People(string name,char sex)
        {
            Console.WriteLine("People的有参构造函数");
            Name = name;
            Sex = sex;
        }
    }



    class Man : People
    {
        //子类被创建的时候,默认会执行父类的无参构造方法,不会执行有参构造方法
        //public Man():base() 自动生成这样的代码,等价于直接执行父类的无参构造方法
        public Man()
        {
            Console.WriteLine("Man的无参构造函数");
           
        }
        //子类中使用base 表示父类
        //this表示当前类
        //在子类的构造方法后面添加 :base 可以直接执行父类的构造方法
        public Man(string name):base(name,'男')
        {
            Console.WriteLine("Man的有参构造函数");

        }
    }
}

访问修饰符测试

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace _04_访问修饰符
{
    internal class Program
    {
        static void Main(string[] args)
        {
            Man man =new Man();
            Console.WriteLine(man.a);
            // Console.WriteLine(man.b);
            Console.WriteLine(man.c);
            //Console.WriteLine(man.d);
            Console.WriteLine(man.e);

        }
    }

       //public:公共的,当前类,子类,实例都可以访问到
       //private:私有的,仅能在当前类内部访问,子类,实例都不能访问
       //internal:只能在当前项目访问
       //protected:只有该类以及子类可以访问.实例不能访问
       //protected internal:能在当前类,子类,实例中访问,在别的项目(引用了这个项目)中,
       可以在子类中访问,实例不能访问

    public class People
    {
        public int a = 2;
        private int b=3;
        internal int c = 4;

        protected  int d = 5;
        protected internal int e = 6;
        public void PeopleFn()
        {
            Console.WriteLine(a);
            Console.WriteLine(b);
            Console.WriteLine(c);
            Console.WriteLine(d);
            Console.WriteLine(e);
        }

    }
    class Man : People
    {
        public void ManFn()
        {
            Console.WriteLine(a);
            //Console.WriteLine(b);
            Console.WriteLine(c);
            Console.WriteLine(d);
            Console.WriteLine(e);
        }

    }
}
//----------------
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using _04_访问修饰符;

namespace _04_测试
{
    internal class Program
    {
        static void Main(string[] args)
        {

            Test test=  new Test();
            Console.WriteLine(test.a);
            // Console.WriteLine(test.c);
           // Console.WriteLine(test.e);



        }
    }
    class Test : People
    {
        public void TestFn()
        {
            Console.WriteLine(a);
            Console.WriteLine(d);
            Console.WriteLine(e);
        }


    }
}


访问修饰符/范围当前类子类实例对象引用当前项目的项目子类引用当前项目实例对象
public
private××××
internal××
protected××
protected internal×

多态_函数重载

方法的重载注意事项:
1.同一个方法的不同重载可以是参数数量不同
2.也可以是参数的类型不同
3.和返回值类型无关,(不同的返回值类型不算重载)

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace _05_多态_函数重载
{
    internal class Program
    {
        static void Main(string[] args)
        {

            //多态指同一个行为具有不同的表现形式的能力

            //多态性可以是静态或者动态的,静态指的是在编译过程中发生的,动态指的
            是在运行过程中发生的
           
            //静态多态:
            //在编译过程中,通过方法重载和运算符重载来实现编译时多态,也称为静态绑定
            或早期绑定

            //动态多态:
            //在运行过程中:通过抽象方法,重写方法,隐藏方法实现运行时多态,也称之为动
            态绑定或后期绑定

            //我们对类进行相同的new行为,出现了不同的效果,这个就可以理解为多态
            new People();
            new People("吴亦凡");
            People p1 = new People();
            p1.Eat();
            p1.Eat("大盘鸡");
            

            Console.WriteLine();
        }
    }
    //
    class People
    {
        public string Name { get; set; }

        //函数的重载
        //可以在同一个范围内,对相同的函数名有多个定义
        //函数的定义必须彼此不同,可以是参数列表中的参数类型不同,也可以是参数的个数不同
        //不能重载只有返回值类型不同的函数声明
        public People()
        {
            Console.WriteLine("无参构造函数");
        }
        public People(string name)
        {
            Console.WriteLine("string类型有参构造函数");
        }
 
        public People(int age)
        {
            Console.WriteLine("int类型的有参构造函数");
        }
        public People(int age,string name)
        {
            Console.WriteLine("int和string类型的有参构造函数");
        }
        public People( string name, int age)
        {
            Console.WriteLine("string和int类型的有参构造函数");
        }

        public void Eat()
        {
            Console.WriteLine("我在吃饭");
        }
        public void Eat(string food)
        {
            Console.WriteLine("我在吃"+ food);
        }
        public void Eat(int count)
        {
            Console.WriteLine($"我今天吃了{count}饭");
        }
        public void Eat(int count,string food)
        {
            Console.WriteLine($"我今天吃了{count},全是{food}");
        }
    }
}

多态_运算符重载

可重载与不可重载的运算符

运算符可重载性
+、-、!、~、++、–这些一元运算符可以进行重载
+、-、*、/、%、&、|、^、<<、>>、=、!=、<、>、<=、>=这些二元运算符可以进行重载,需要注意的是某些运算符必须成对重载
&&、||无法重载逻辑运算符
(type)var_name强制类型转换运算符不能重载
+=、-=、*=、/=、%=、&=、|=、^=、<<=、>>=复合赋值运算符不能显式重载。 但在重载二元运算符时,也会隐式重载相应的复合赋值运算符,例如重载了+运算符也会隐式的重载+=
^、=、.、?.、? : 、??、??=、…、->、=>、as、await、checked、unchecked、default、delegate、is、nameof、new、sizeof、stackalloc、switch、typeof这些运算符无法进行重载

注意:比较运算符必须成对重载,也就是说,如果重载一对运算符中的任意一个,则另一个运算符也必须重载。比如==!=运算符、<>运算符、<=>=运算符。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace _06_多态_运算符重载
{
    internal class Program
    {
        static void Main(string[] args)
        {
            Box b1=new Box() { Width=10,Height=10,Length=10};
            Box b2 = new Box() { Width = 20, Height = 20, Length = 20 };
        

            //计算这两个盒子的体积的和
            Console.WriteLine(b1 + b2);
            //计算两个盒子相减,生成一个新的Box
            Box b3 = b2 - b1;
            Console.WriteLine(b3.Height);

            //比较两个盒子的大小
            Console.WriteLine(b1>b2);
            Box b4 = b1++;

            
        }
    }
    class Box
    {

        public double Length { get; set; }
        public double Width { get; set; }
        public double Height { get; set; }
        public double Volume
        {
            get
            {
                return Length * Width * Height;
            }
        }

        //我们可以重新定义某个类的运算符,我们自定义的运算符,可以对我们的对象进行运算操作

        //重载+运算符 计算两个盒子的体积
        //一个运算符的重载,其实就是一个方法,当对该类的对象进行对应的运算符操作的时候,
        会自动执行这个重载的运算符方法

        //格式:public static 返回值类型 operator 要重载的运算符(参数列表){}

        //+ 运算符重载接收两个参数 表示进行运算的两个对象
        public static double operator +(Box box1,Box box2)
        {

            return  box1.Volume + box2.Volume;
        }
        public static Box operator -(Box box1, Box box2)
        {

            return new Box
            {
                Width = box1.Width - box2.Width,
                Height = box1.Height - box2.Height,
                Length = box1.Length - box2.Length
            };
        }
        public static bool operator >(Box box1, Box box2)
        {

            return box1.Volume >box2.Volume;
        }
        public static bool operator <(Box box1, Box box2)
        {

            return box1.Volume < box2.Volume;
        }
        public static bool operator ==(Box box1, Box box2)
        {

            return box1.Volume == box2.Volume;
        }
        public static bool operator !=(Box box1, Box box2)
        {

            return box1.Volume != box2.Volume;
        }
        public static Box operator ++(Box box)
        {
            box.Width++;
            box.Height++;
            box.Length++;
            return box;
        }
        public static Box operator --(Box box)
        {
            box.Width--;
            box.Height--;
            box.Length--;
            return box;
        }
    }
}

抽象类

C#中可以创建抽象类,用于提供类的部分成员实现,当某一个类继承自这个抽象类的时候,需要手动实现这个类中的抽象成员

抽象类中可以包含抽象方法,这个抽象方法不能去实现,而是在某个类继承自这个抽象类的时候实现

总结: 抽象类和普通类的区别?

  1. 抽象类不能实例化,普通类可以实例化
  2. 抽象类中不一定要有抽象方法,普通类中不能有抽象方法
  3. 抽象类可以和普通类一样,有普通方法
  4. 抽象类可以继承自抽象类,子类如果不是抽象类,则必须重写抽象类中的全部抽象方法
  5. 抽象方法就是被子类重写的,所以不能使用private修饰符
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace _07_抽象类
{
    internal class Program
    {
        static void Main(string[] args)
        {

            //抽象类:就是指设计为被继承的类,抽象类只能被用作其他的类的基类

            //new Print();
           ColorPrint p1=  new ColorPrint();

            p1.Print("6666");

        }
    }

    // 使用 abstract  class   创建一个抽象类 写法和class相同
    abstract class Printer
    {
        public string Name { get; set; }
        public int Price { get; set; }

        //抽象类中可以定义抽象方法
        //给某个方法添加一个abstract关键字,把这个方法修饰成抽象方法,抽象方法不需要也不能拥有内容
         public abstract  void Print(string value);
        
    }
    //当某个非抽象类继承自一个抽象类之后,必须实现这个类中的抽象方法
    class ColorPrint:Printer
    {
        //override 重写和实现抽象类中的抽象方法
        public override void Print(string value)
        {
            Console.WriteLine("打印彩色的内容"+value);
        }
    }
    class BawPrint : Printer
    {
        public override void Print(string value)
        {
            Console.WriteLine("打印黑白内容"+value);
        }
    }
}




虚方法

总结:抽象方法和虚方法的区别?

  1. 抽象方法只能定义在抽象类中,虚方法可以定义在普通类中
  2. 抽象方法不可以有内容,必须在派生类中实现,虚方法可以有内容,可以不再派生类中实现,不实现则使用基类的方法
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace _08_虚方法
{
    internal class Program
    {
        static void Main(string[] args)
        {

            //类的动态多态,是由抽象方法和虚方法实现的

            //虚方法可以定义在一个普通的类中,可以理解为一个类中的抽象方法,只是这个方法可以在类中实现,也可以在派生类中实现
            Chinese chinese = new Chinese();
            chinese.Speak();
            Man man =new Man();
            man.Speak();

            
        }
    }

    class People
    {
        public string Name { get; set; }


        //给某个方法添加一个 virtual 关键字,把这个方法修饰成虚方法,虚方法可以有实现(内容)
        public virtual  void Speak()
        {
            Console.WriteLine("打招呼");
        }
    }
    class Chinese : People
    {
        //override 重写和覆盖父类的虚方法
        public override void Speak()
        {
            Console.WriteLine("吃了没?");
        }
    }
    class Man : People
    {

    }
}




new 和override

相同: new和override 都可以对基类的成员"覆盖"
不同

  1. new 隐藏基类的成员(覆盖基类所有的成员的虚方法,非虚方法)
  2. override是 覆盖基类成员(只能重写基类的抽象方法和虚方法)
  3. new 是隐藏, 基类和派生类各持一份,互不干扰 对象是什么类型 使用对应的类的方法
  4. override 是覆盖 将会重写基类的虚方法和抽象方法,只此一份,不管是什么类型,都只有一个
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace _09_new_和override
{
    internal class Program
    {
        static void Main(string[] args)
        {
            

            Man m1=new Man();
            People m2=new Man();

            m1.Test1();//Man-Test1
            m2.Test1();//People_Test1
            m1.Test2();//Man-Test2
            m2.Test2();//Man-Test2



            Woman w1=new Woman();
            People w2 = new Woman();
            w1.Test1();
            w2.Test1();
            w1.Test2();
            w2.Test2();
        }
    }
    class People
    {
        public void Test1()
        {
            Console.WriteLine("People_Test1");
        }

        public virtual void Test2()
        {
            Console.WriteLine("People_Test2");
        }

        public virtual void Test3()
        {
            Console.WriteLine("People_Test3");
        }

    }
    class Man : People
    {
        //当类中的成员是虚方法的时候,可以使用override进行处理

        public new void Test1()
        {
            Console.WriteLine("Man-Test1");
        }

       
        //当派生类和基类中拥有同名的成员的时候,编译器会发出一个警告"隐藏继承的成员xxxx.如果是有意隐藏,请使用new关键字"
        public override void Test2()
        {
            Console.WriteLine("Man-Test2");
        }


    }
    class Woman : People
    {
        public new void Test1()
        {
            Console.WriteLine("Woman-Test1");
        }


     
        public override void Test2()
        {
            Console.WriteLine("Woman-Test2");
        }
        public override void Test3()
        {
            Console.WriteLine("Woman-Test3");
        }
    }
}

密封类和静态类

  1. 给某个类添加一个 sealed 关键字,把这个类修饰成密封类,密封类不能被其他的类继承
  2. 给某个类添加一个 static 关键字,把这个类修饰成静态类,静态类不能实例化(不能new)也不能被继承,并且静态类中只能拥有静态成员

注意:抽象类的作用就是让别人继承的,抽象类不能被定义为密封类

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace _10_密封类和静态类
{
    internal class Program
    {
        static void Main(string[] args)
        {
            new Test();
           // new Test3();
        }
    }

    sealed class Test
    {

    }

    //    class Test2:Test { 

    //    }

  
    static class Test3
    {
        public static int a = 1;

    }

 
}

结构体

类和结构的区别:
1.结构体是值类型,类是引用类型
2.结构体不能继承其他的类和结构体,也不能被类和其他的结构体所继承
3.不能定义无参数的构造方法,可以定义有参的构造方法
4.不能对结构体的字段和属性进行初始化

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace _11_结构体
{
    internal class Program
    {
        static void Main(string[] args)
        {

            Book book = new Book();
            book.Name = "坏蛋是怎么样炼成的";
            book.Price = 100;
            book.ShowInfo();
            Book book2 = new Book();
            book.Price = 22;
            book2.ShowInfo();
        }
    }
    //结构体是值类型的数据,它可以让单一的变量可以存储多个数据.和类及其相似,也可以存储字段,属性,方法,可以理解为结构体就是值类型的对象
    //格式: struct 结构体的名字 {内容}
    struct MyStruct
    {

        //和类相似,在结构体中可以定义类似于成员的结构成员
        //字段
        private int a;
        //属性
        public string A { get; set; }
        public void Test()
        {

        }
    }
    struct Book
    {
        public string Name { get; set; }
        public double Price { get; set; }
        public void ShowInfo()
        {
            Console.WriteLine($"{Name}的售价为{Price}");
        }

        //结构体不能定义无参的构造方法
        //public Book() { 

        //}
        public Book(string name, double price)
        {

            this.Name = name;
            this.Price = price;
        }

    }
    //struct Book1 : Book
    //{

    //}

    //类和结构的区别:
    //1.结构体是值类型,类是引用类型
    //2.结构体不能继承其他的类和结构体,也不能被类和其他的结构体所继承
    //3.不能定义无参数的构造方法,可以定义有参的构造方法
    //4.不能对结构体的字段和属性进行初始化
}

上期习题答案

  1. 验证一个车牌号码是否符合中国大陆的规范

    // 例如豫A12345、粤BD12345Z等
    Regex regexPlateNumber = new Regex(@"^[\u4e00-\u9fa5][A-Z](([A-Z0-9]{6})|([DF][A-HJ-NP-Z0-9]{5}))$");
    
  2. 正则验证邮箱格式是否正确

    // 基本电子邮件地址匹配,注意这不包括所有有效邮件地址的可能性,只是最常见的形式
    Regex regexEmail = new Regex(@"^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$");
    
  3. 判断 xxxx-xx-xx 格式的字符是否为有效日期(假设月份和日期总是有效)

    // 简化版,不验证实际每个月的具体天数或闰年逻辑,只会检测基础格式。
    Regex regexSimpleDate = new Regex(@"^\d{4}-(0[1-9]|1[0-2])-(0[1-9]|[12]\d|3[01])$");
    

现在让我们将这些正则表达式应用到 C# 代码中以进行实际验证:

using System;
using System.Text.RegularExpressions;

class Program {
    static void Main() {
        Console.WriteLine("请输入一个车牌号码:"); 
        string plateNumberInput = Console.ReadLine();
        var regexPlateNumber = new Regex(@"^[\u4e00-\u9fa5][A-Z](([A-Z0-9]{6})|([DF][A-HJ-NP-Z0-9]{5}))$");
        bool isPlateNumberValid = regexPlateNumber.IsMatch(plateNumberInput);
        Console.WriteLine(isPlateNumberValid ? "车牌有效。" : "车牌无效。");

        Console.WriteLine("\n请输入一个邮箱地址:"); 
        string emailInput = Console.ReadLine();
        var regexEmail = new Regex(@"^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$");
        bool isEmailValid = regexEmail.IsMatch(emailInput);
        Console.WriteLine(isEmailValid ? "邮箱地址有效。" : "邮箱地址无效。");

        Console.WriteLine("\n请输入一个日期(格式为 xxxx-xx-xx):"); 
        string dateInput = Console.ReadLine();
        var regexSimpleDate = new Regex(@"^\d{4}-(0[1-9]|1[0-2])-(0[1-9]|[12]\d|3[01])$");
        bool isDateValid = regexSimpleDate.IsMatch(dateInput);
        Console.WriteLine(isDateValid ? "日期有效。" : "日期无效。");
    }
}

运行程序后,在控制台中输入相应信息将对上述各项内容进行校验。

请注意,通用电子邮件验证是一个复杂任务且存在边缘情况;要创建一个能够涵盖所有合法电子邮件地址的正则表达式非常困难并且不太实际。上面给出的电子邮件正则表达式遵循基本标准但未涉及到所有复杂场景。

同理,对于日期也是如此——简单地验证日期字符串格式而不考虑月份和年份特有的日期规则会导致非法日期(如 11 月 31 日)被判断为有效。如果您需要更准确地验证,请考虑使用内置于 .NET 的 DateTime 类型解析功能:

DateTime temp;
bool isValidDate = DateTime.TryParseExact(dateInput, "yyyy-MM-dd", CultureInfo.InvariantCulture, DateTimeStyles.None, out temp);

这种方式调用 DateTime.TryParseExact 方法可以比任何正则表达式都更准确地检验日期字符串是否表示有效日期。

本期习题

  1. 定义一个Animal类,拥有Name、MaxAge(最大寿命)、NowAge(当前的年龄,生成对象时随机设置)、Sex,

    一个Dog类,继承自Animal类,拥有Speak方法,发出汪汪汪的声音

    一个Cat类,继承自Animal类,拥有Speak方法,发出喵喵喵的声音

  2. 定义一个类,实现计算面积 可以计算矩形,正方形,梯形的面积(多态)

  3. 定义一个类实现图书馆管理学生借书权限(抽象)

    对于本科生来说,只能借5本书,硕士生可以借10本,而博士生则可以借15本书

  4. 定义一个抽象类,拥有属性账号、密码、(抽象)支付方法

觉得文章还不错,可以关注,点赞,收藏。主页有C#教程专栏,欢迎订阅!!!
图片来源网络

标签:Console,C#,多态,System,WriteLine,new,using,抽象类,public
From: https://blog.csdn.net/2401_82410658/article/details/136915256

相关文章

  • JavaScript object.is()和严格相等、非严格相等的区别
    1.==(相等运算符)        当使用==比较两个值时,如果它们的类型不同,JavaScript会尝试将它们转换为一个共同的类型,然后再进行比较。这个过程称为类型转换或类型强制。0=='0'//true,因为字符串'0'会转换为数字01==true//true,因为布尔值true会转换为数字1nul......
  • Synchronized的底层实现原理(转载)
    synchronized一.synchronized解读1.1简单描述synchronized关键字解决的是多个线程之间访问资源的同步性,synchronized翻译为中文的意思是同步,也称之为同步锁。synchronized的作用是保证在同一时刻,被修饰的代码块或方法只会有一个线程执行,以达到保证并发安全的效果。1.2特性......
  • install openjdk 8 mac m1
    在AppleSilicon(M1/M2)的Mac上安装OpenJDK8需要使用到Rosetta2,因为OpenJDK8默认没有为ARM架构提供官方支持。这里有几种方法可以试着安装OpenJDK8:使用Homebrew通过Rosetta2安装:首先,确保你有Rosetta2安装。可以通过下面的命令安装Rosetta2:/usr/sbin/s......
  • [转]WPF 使用 Dispatcher 的 InvokeAsync 和 BeginInvoke 的异常处理差别
    一般认为WPF的Dispatcher的InvokeAsync方法是BeginInvoke方法的平替方法和升级版,接近在任何情况下都应该在业务层使用InvokeAsync方法代替BeginInvoke方法。然而在异常的处理上,这两个方法还是有细微的差别的,不能说是坏事,依然可以认为使用InvokeAsync方法代替BeginI......
  • SQL的nvarchar类型的中文内容,显示有乱码问题解决
    今天上线一个ASP项目升级为MVC的项目。原系统的ASP语言保存到SQLserver中nvarchar字段内容显示乱码了(显示有&#代码)。下图是SQLmanagementstudio的结果截图:左1列是经修正转化的可正常显示右1列OriStr为原数据库中nvarchar的内容。(ASP程序保存到数据库的原始数据)【产生乱......
  • AT_agc044_c
    problem&blog由于看到和三进制有关的操作,可以想到建造每个结点都有三个儿子的Trie。考虑维护两种操作。1.Salasa舞对于这种操作,就是把每一个节点的第一个儿子和第二个儿子交换。所以两个节点打个标记即可2.Rumba舞本质即为\(0\to1,1\to2,2\to0\)。前两者不用进......
  • vector resize和reserve的区别
    在C++的标准库中,resize()和reserve()是用于操作std::vector容器的两个不同函数,它们的作用和效果有所区别。resize()函数resize()函数用于改变std::vector容器的大小,即调整容器中元素的数量。如果当前vector的大小小于指定的大小,resize()会在容器末尾添加默认构......
  • 备考ICA----Istio实验4---使用 Istio 进行金丝雀部署
    备考ICA----Istio实验4—使用Istio进行金丝雀部署上一个实验已经通过DestinationRule实现了部分金丝雀部署的功能,这个实验会更完整的模拟展示一个环境由v1慢慢过渡到v2版本的金丝雀发布.1.环境清理kubectldeletegw/helloworld-gatewayvs/helloworlddr/helloworld......
  • UE5中简易的UI管理框架(c++版,UE5.1)
    需求说明:在UE项目开发中,当UI界面较多的时候,就需要有一个管理功能出现,负责UI的生成、销毁、禁用等功能。基于此需求,采用栈先进后出的数据接口,编写了一个简易的UI管理框架。功能说明:1.支持UI的自动创建2.支持UI的按开启顺序关闭3.支持一件关闭所有UI4.支持开启当前UI后,禁......
  • echarts 实现漏斗图中心、右侧同时显示
    效果图:代码实现:letoption={ tooltip:{ trigger:'item', formatter:'{b}:{c}%' }, labelLine:{ show:true }, series:[{ name:'漏斗', type:'funnel', top:10, ......