C# 接口_索引器_命名空间

文章目录

接口

  1. 接口中只能定义属性,不能定义字段
  2. 不能包含静态成员
  3. 接口的成员不能用修饰符,所有成员默认为public,即使是public也不能写
  4. 类或者结构体实现的时候,类的成员相对于接口成员,只能多,不能少,如果接口中规定的属性拥有get和set,类中必须都有,接口规定只有get,类中可以有get和set
  5. 当类实现多个接口的时候,使用,分割
  6. 当类同时继承基类和接口的时候,必须把基类放在前面

代码示例

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)
        {

            //接口是指一组成员,而不对他们的成员进行实现的引用类型,只能被类和结构体所实现,
            类和结构体继承这个接口的时候,必须实现接口中定义的所有的成员



            //接口只是一种规范,不具备存储数据和定义方法的能力
            //类和结构体实现这个接口的时候,以这个接口的规范为准,进行一一实现,具体怎么实现,
            还是由类和结构体决定
            
            //接口:指定规则,应该有什么
            //类和结构体:实现接口指定的规则,具体怎么有


        }
    }
        //定义一个接口 接口的名字一般以I开头
        //格式:interface 接口的名称{成员}
    interface IBook { 

            //属性
            string Name { get; set; }
            double Price { get; set; }
            void Fn();
            void Fn(string v);

     }

    interface IPaper
    {
        string Type { get; set; }
        string Color { get; set; }
        double Height { get;set; }
    }

    //让某个类实现这个接口,某个类或者结构体实现了这个接口的时候,必须实现这个接口的所有的成员
    //一个类可以使用,实现多个接口
    class Book : IBook, IPaper
    {
        public string Name { get; set; }
        public double Price { get; set; }
        public string Color { get; set; }
        public string Type { get; set; }
        //实现的类总可以拥有更多的成员,但是不能少
        private double price;
        public double Height { get; set; }
        public void Fn() { }
        public void Fn(string v) { }

    }


    interface IPeople
    {
        string Name { get; set; }
        char Sex { get; set; }
        int Age { get; set; }




    }
    interface IStudent
    {
        string StudentNo { get; set; }
        double Age { get; set; }
    }
    class People : IPeople
    {
        public string Name { get; set; }
        public char Sex { get; set; }
        public int Age { get; set; }
    }

    class Student : People, IStudent
    {
        public string StudentNo { get; set; }
        //当基类拥有和接口中同名的属性的时候,派生类不需要自己实现,也可以使用new关键字重新实现(了解);
        public  new double Age { get; set; }
        public void Study()
        {
            Console.WriteLine("我爱学习");
        }
    }



    }

多接口

  1. 当一个类实现的多个接口中拥有相同的类型和相同的属性,只实现一个即可

  2. 当一个类实现的多个接口中拥有不同类型的相同属性,需要使用显示接口实现

  3. 显示接口的实现,不需要也不能加访问修饰符,这个成员访问需要将对象标识为对应的接口的类型

    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)
    {

         }
    
     }
    
     interface IA
     {
         string A { get; set; }
         string B { get; set; }
         int D { get; set;}
         void Fn(int v);
     }
    
    
     interface IB
     {
        
         string B { get; set; }
         string C { get; set; }
         string D { get;set; }
         void Fn(string v);
     }
    
     //类可以实现多个接口
     class Tset : IA, IB
     {
         public string A { get; set; }
         //当一个类实现的多个接口中拥有相同的类型和相同的属性,只实现一个即可
         public string B { get; set; }
         
    
         //当一个类实现的多个接口中拥有不同类型的相同属性,需要使用显示接口实现
         //显示接口的实现,不需要也不能加访问修饰符,这个成员访问需要将对象标识为对应的接口的类型
         int IA.D { get; set; }
         string IB.D { get; set; }
         public bool D { get; set; } 
    
         //因为方法可以重载,所以可以直接重载两个接口的方法
         public void  Fn(int v) { }
         public void Fn(string v) { }
     }
    

    }

接口的继承

  1. 一个接口可以继承另一个接口,如果接口B继承了接口A,某个类实现了接口B的时候,要实现A和B的所有的成员
  2. 抽象类和接口有什么异同?
  • 相同点:

  • 1.抽象类和接口都不能实例化 不能new

  • 2.都可以包含未实现的方法,由派生类去实现

  • 不同点:

  • 1.抽象类可以包含非抽象成员 接口只能包含抽象成员(这里的抽象可以理解无实现)

  • 2.抽象类只能被实现一个 而接口可以被实现多个(多个接口用逗号隔开·)

  • 3.抽象类的派生类需要使用override去覆写抽象类的抽象成员 接口派生类直接覆写

  • 4.抽象类可以包含访问修饰符 接口不能有访问修饰符

  • 5.抽象类可以包含属性 字段 方法(只能是抽象方法) 接口只能包含属性和方法(不能有抽象方法)

    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)
    {

          }
      }
      interface IPeople
      {
          string Name { get; set; }
          int Age { get; set; }
      }
    
      //一个接口可以继承另一个接口,如果接口B继承了接口A,某个类实现了接口B的时候,要实现A和B的所有的成员
      interface IStudent : IPeople
      {
          string StudentId { get; set;}
         void Study();
    
      }
    
    
      class Student : IStudent
      {
          public string StudentId { get => throw new NotImplementedException(); set => throw new NotImplementedException(); }
          public string Name { get => throw new NotImplementedException(); set => throw new NotImplementedException(); }
          public int Age { get => throw new NotImplementedException(); set => throw new NotImplementedException(); }
    
          public void Study()
          {
              throw new NotImplementedException();
          }
      }
    

    }

索引器

索引器: 一种可以让我们使用 "索引" 来访问对象的一种方式

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)
        {
            //索引器: 一种可以让我们使用 "索引" 来访问对象的一种方式

           ClassRoom room = new ClassRoom();
           room.Add(new Student() { Name = "吴亦凡", Sex = "男" });
           room.Add(new Student() { Name = "罗志祥", Sex = "男" });
           room.Add(new Student() { Name = "李云迪", Sex = "女" });
           room.Add(new Student() { Name = "郑爽", Sex = "女" });


            //需求:想访问数组中的数据一样,通过索引获取班级中学生的姓名

            Console.WriteLine(room[0].Name); 
            Console.WriteLine(room[1].Name);
            //通过索引这是值,将会执行索引器中的set代码块
            room[3]=new Student() { Name="李易峰",Sex="男"};


            Student s = room["吴亦凡"];//返回Name属性为吴亦凡的那个对象


        }
    }
    class Student
    {
        public string Name { get; set; }
        public string Sex { get; set; }

    }
    class ClassRoom
    {
        public string No { get; set; }
        public string Name { get; set; }

        private List<Student> student =new List<Student>();
        public void Add(Student s)
        {
            student.Add(s);
        }

        //给类中添加一个索引器,这个类的实例就可以想数组一样通过索引进行访问了
        //格式:public 返回值类型 this[索引的类型 索引] {}
        public Student this[int index]
        {
            //通过索引来访问数据的时候执行
            get
            {
                //当前访问的索引
                Console.WriteLine(index);

                return student[index];
            }
            //通过索引来设置这个数据的时候执行(如果没有set代码块,表示这个索引器是只读)
            set
            {
                student[index] = value;
            }


        }
        public Student this[string index]
        {
            get
            {
                //根据传入的值,也就是学生的姓名进行对象的查找
                //for (int i = 0; i < student.Count; i++)
                //{
                //    if (student[i].Name==index)
                //    {
                //        return student[i]; 
                //    }
                //}
                //return null;

                return student.Find(student => student.Name == index);
            }
        }
    }
}

索引器练习

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)
        {
            Student student =new Student(new string[] {"吴凡","罗祥","李迪"});
            Console.WriteLine(student.Name);
            Console.WriteLine(student[0]);
            Console.WriteLine(student[1]);


            student[3] = "郑";
            Console.WriteLine(student[3]);
        }
    }
    class Student
    {
        // 存储所有学生的名字
        string[] names;
        //Name 设置默认值 为第一个学生的名字
        public string Name { get => names[0]; }
        public Student(string[] names) { 

            this.names = names;
        }

        public string this[int index] {

            //get
            //{
            //    return names[index];
            //}
            get => names[index];
            set
            {
                if (index>=Name.Length)
                {
                    string[] NewNames=new string[index+1];
                    Array.Copy(names, NewNames, names.Length);
                    NewNames[index] = value;
                    names = NewNames;
                }
                else
                {
                    names[index]=value;
                }

            }
        
        }




    }
}

命名空间

  1. 我们的代码越来越多,类越来越多,代码写在同一个文件夹中会导致某个文件结构复杂,代码格式杂乱.命名空间可以让我们在不同的文件中书写代码,不同的文件互相引用

  2. namespace 用来定义一个命名空间 命名空间以大驼峰命名法命名

  3. 如果出现多个命名空间下拥有相同的成员,我们使用的时候会导致不明确的指向

  4. 可以使用 重命名的方案会进行处理
    using myCar1 = Car1.Car;
    using myCar2 = Car2.Car;

    //using 命名空间的名称 引用其他的命名空间
    using fanfan;

    using luozhixiang.xiangxiang;

    //如果出现多个命名空间下拥有相同的成员,我们使用的时候会导致不明确的指向
    //可以使用 重命名的方案会进行处理
    using myCar1 = Car1.Car;
    using myCar2 = Car2.Car;

    //namespace 用来定义一个命名空间 命名空间以大驼峰命名法命名
    //格式:namespace 命名空间的名称

    //我们的代码越来越多,类越来越多,代码写在同一个文件夹中会导致某个文件结构复杂,代码格式杂乱
    //命名空间可以让我们在不同的文件中书写代码,不同的文件互相引用
    namespace _07_命名空间
    {
    internal class Program
    {
    static void Main(string[] args)
    {
    System.Console.WriteLine("控制台打印");

             //在同一个项目的不同文件中,可以直接访问相同命名空间下的其他类
             People people = new People();
             Student student = new Student();
    
    
             //当某个类和当前类不再同一个命名空间下的时候
             //使用 命名空间.目标名称 来引用
    
             fanfan.Book book1 = new fanfan.Book();
    
             //我们如果频繁使用其他命名空间的类,结构体 接口等,需要using关键字引用
             //使用using引用之后,就可以把它内部的成员当做相同命名空间下的成员来使用了
             fanfan.Book book2 = new fanfan.Book();
             Book book3 =new Book();
    
             luozhixiang.xiangxiang.C c = new luozhixiang.xiangxiang.C();
    
             C c2 = new C();
    
             luozhixiang.Tool.Test.AA.A a=new luozhixiang.Tool.Test.AA.A();
    
             Car1.Car cc1 =new Car1.Car();
             Car2.Car cc2 = new Car2.Car();
    
             myCar1 my1=new myCar1();
         }
     }
    

    }

引用静态类

静态成员可以在using static 引入之后 直接访问

非静态成员 使用实例进行访问

//using xxx 只能引入命名空间 System.Console 不是命名空间 而是一个类 所以不能被引用
//using System.Console;


//我们可以使用using static 引用类, 就可以直接使用类中的静态成员了

using  static System.Console;
using static fanfan.Test;
using fanfan;

namespace _08_引用静态类
{
    internal class Program
    {
        static void Main(string[] args)
        {
            WriteLine("控制台打印");
            WriteLine("控制台打印");

            //静态成员可以在using static 引入之后 直接访问
            Fn1();
            //非静态成员 使用实例进行访问
           new Test().Fn2();
        }
    }
}

引用其他项目

引用同一解决方案下的其他项目

​ 1.当前项目中的"引用"上,右键点击

​ 2.在弹出的菜单中选择添加引用

​ 3.选择 "项目" ==> "解决方案"

​ 4.勾选需要引用的项目

​ 5.点击确定

​ 6.根据对应的项目的命名空间进行引用

引用其他解决方案的项目

​ 1.当前项目中的"引用"上,右键点击

​ 2.在弹出的菜单中选择"添加引用"

​ 3.选择"项目"==>"解决方案"

​ 4.点击"浏览"

​ 5.找到对应解决方案中对应的项目文件 "解决方案目录"--> 项目目录-->bin -->Debug --->Next.x ---> xxx.dll或者 xxx.exe

​ 6.点击确定

​ 7.根据对应项目的命名空间进行引用

上期习题答案

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)
        {
        }
    }
    class Animal
    {
        //Name、MaxAge(最大寿命)、NowAge(当前的年龄,生成对象时随机设置)、Sex
        public string Name { get; set; }
        public int MaxAge { get; set; }
        private int nowAge;
        public int NowAge
        {
            get => nowAge;
            set
            {
                if (value > MaxAge)
                {
                    throw new Exception("年龄超出最大年龄限制");
                }
                nowAge = value;
            }
        }
        public char Sex { get; set; }
        // 一个随机对象,根据最大年龄设置当前年龄
        Random random = new Random();

        public Animal(int maxAge)
        {
            MaxAge = maxAge;
            // 在构造方法中进行年龄的初始化
            NowAge = random.Next(maxAge + 1);
        }
    }
    class Dog : Animal
    {
        // 指定一个无参的构造,当没有传递参数时指定MaxAge为34
        public Dog() : base(34) { }
        // 一个有参的构造,当传递参数时指定MaxAge为传递的值
        public Dog(int maxAge) : base(maxAge) { }

        public void Speak()
        {
            Console.WriteLine("汪汪汪");
        }
    }
    class Cat : Animal
    {
        // 指定一个无参的构造,当没有传递参数时指定MaxAge为39
        public Cat() : base(39) { }
        // 一个有参的构造,当传递参数时指定MaxAge为传递的值
        public Cat(int maxAge) : base(maxAge) { }

        public void Speak()
        {
            Console.WriteLine("喵喵喵");
        }
    }
    class Area
    {
        /// <summary>
        /// 计算矩形的面积
        /// </summary>
        /// <param name="lenght">长</param>
        /// <param name="width">宽</param>
        /// <returns>矩形的面积</returns>
        public static int GetArea(int lenght, int width)
        {
            return lenght * width;
        }

        /// <summary>
        /// 计算正方形的编辑
        /// </summary>
        /// <param name="lenght">边长</param>
        /// <returns>正方形的面积</returns>
        public static int GetArea(int lenght)
        {
            return lenght * lenght;
        }
        /// <summary>
        /// 计算梯形的面积
        /// </summary>
        /// <param name="top">上底长度</param>
        /// <param name="botoom">下底的长度</param>
        /// <param name="h">高度</param>
        /// <returns></returns>
        public static int GetArea(int top, int botoom, int h)
        {
            return (top + botoom) * h / 2;
        }
    }
    //抽象学生类
    abstract class Student
    {
        public abstract int Authority();
    }
    //本科生
    class Undergraduate : Student
    {
        public override int Authority()
        {
            return 5;
        }
    }

    //硕士生
    class Postgraduate : Student
    {
        public override int Authority()
        {
            return 10;
        }
    }
    //博士生
    class Doctor : Student
    {
        public override int Authority()
        {
            return 15;
        }
    }
    abstract class Pay
    {
        public string Id { get; set; }//账号
        public string Pws { get; set; }//密码
        public abstract void payment(double v);//支付的方法,应该接收金额
        public abstract void payment(double v, string account);//支付的方法,应该接收金额
    }
    class WeiXinPay : Pay
    {
        public override void payment(double v)
        {
            Console.WriteLine($"使用微信支付{v}圆,账号是{Id},密码{Pws}");
        }
        public override void payment(double v, string account)
        {
            Console.WriteLine($"使用微信支付给{account}{v}元,账号是{Id},密码{Pws}");
        }

    }
    class AliPay : Pay
    {
        public override void payment(double v)
        {
            Console.WriteLine($"使用支付宝支付{v}圆,账号是{Id},密码{Pws}");
        }
        public override void payment(double v, string account)
        {
            Console.WriteLine($"使用支付宝支付给{account}{v}元,账号是{Id},密码{Pws}");
        }

    }
}

本期习题

  1. 创建一个用于存储某公司员工信息的类Employee,并且可以通过索引来访问员工的姓名和年龄。(提示:使用字典)

    Employee employee = new Employee();

                employee[22] = "fanfan";   // 员工年龄22,名字 fanfan
                employee[22]  = "luoluo"; // 员工年龄22,名字 luoluo
                employee[23] = "Bob";  员工年龄23,名字 Bob
                employee["aa"] = 25;
                employee["Bob"] = 29; //修改Bob的年龄为29
    
  2. 创建一个名为DictionaryWrapper的类,它包装了一个Dictionary对象,并提供了一个索引器,允许我们通过键的部分名称来访问字典中的值。(提示,索引器可以接收多个参数)

    DictionaryWrapper dictionaryWrapper = new DictionaryWrapper();

    // 设置字典中的键值对
    dictionaryWrapper["dog"] = "狗";
    dictionaryWrapper["cat"] = "猫";
    dictionaryWrapper["elephant"] = "大象";
    dictionaryWrapper["dolphin"] = "海豚";
    
    // 输出字典中的值
    Console.WriteLine("通过完整键访问:");
    Console.WriteLine("dog的值是:" + dictionaryWrapper["dog"]);    // 狗
    Console.WriteLine("cat的值是:" + dictionaryWrapper["cat"]);    // 猫
    Console.WriteLine("elephant的值是:" + dictionaryWrapper["elephant"]);  // 大象
    Console.WriteLine("dolphin的值是:" + dictionaryWrapper["dolphin"]);    // 海豚
    
    Console.WriteLine("\n通过键的部分名称访问:");
    Console.WriteLine("以\"do\"开头的键的第一个值是:" + dictionaryWrapper["do", 0]);   // 狗
    Console.WriteLine("以\"do\"开头的键的第二个值是:" + dictionaryWrapper["do", 1]);   // 海豚
    
  3. 将练习1中的类在其他的项目中使用

  4. 将练习2中的类提取到另一个解决方案,并在当前项目中使用

相关推荐
weixin_51454889几秒前
机器学习课程学习周报十五
人工智能·学习·机器学习
小码农<^_^>2 分钟前
c++继承(下)
开发语言·c++
非著名架构师5 分钟前
js混淆的方式方法
开发语言·javascript·ecmascript
Themberfue6 分钟前
基础算法之双指针--Java实现(下)--LeetCode题解:有效三角形的个数-查找总价格为目标值的两个商品-三数之和-四数之和
java·开发语言·学习·算法·leetcode·双指针
慢成长7 分钟前
如何创建虚拟环境并实现目标检测及验证能否GPU加速
人工智能
AIGC破防黑吗喽7 分钟前
Midjourney零基础学习
人工智能·gpt·学习·ai·stable diffusion·midjourney·ai绘画
AI大模型-王哥8 分钟前
微软GraphRAG实战解析:全局理解力如何超越传统RAG
人工智能·microsoft·大模型·ai大模型·大模型学习·大模型入门·大模型教程
会飞的Anthony9 分钟前
基于Python的人工智能应用案例系列(15):LSTM酒类销售预测
人工智能·酒类预测
深山夕照深秋雨mo15 分钟前
在Java中操作Redis
java·开发语言·redis
努力的布布20 分钟前
SpringMVC源码-AbstractHandlerMethodMapping处理器映射器将@Controller修饰类方法存储到处理器映射器
java·后端·spring