C#从入门到精通(5)

发布于:2025-04-02 ⋅ 阅读:(15) ⋅ 点赞:(0)

   

目录

第十二章 其他基础知识

(1)抽象类和方法

(2)接口

(3)集合与索引器

(4)委托和匿名方法

(5)事件

(6)迭代器

(7)分部类

(8)泛型

第十三章 文件操作

(1)基本知识

(2)判断文件是否存在

(3)创建文件

(4)复制文件

(5)移动文件

(6)删除文件

(7)获取文件信息

第十四章 文件夹操作

(1)Directory与DirectoryInfo类

(2)判断文件夹是否存在

(3)创建文件夹    

(4)移动文件夹

(5)删除文件夹

(6)遍历文件夹

第十五章 流操作类

(1)流操作

(2)流的类型

(3)文件流

(4)对文件内容进行操作

(5)文本文件的读写


    学习视频——C#从入门到精通(第六版)_哔哩哔哩_bilibili

第十二章 其他基础知识

(1)抽象类和方法

        如果一个类不与具体的事物相联系,而只表达一种抽象的概念或行为,仅仅作为其派生类的一个基类,这样的类就可以声明为抽象类,在抽象类中声明方法时,如果加上abstract关键字,则为抽象方法,抽象方法不提供具体实现。例如

public abstract class test
{
    public abstract void method();
}

示例

  public abstract class Vehicle
  {
      public string name {  get; set; }
      public abstract void move();
  }
  public class Car:Vehicle
  {
      public override void move()
      {
          Console.WriteLine("{0}在公路上形式",name);
      }
  }
  public class Train:Vehicle
  {
      public override void move() 
      { 
          Console.WriteLine("{0}在铁路上行驶",name); 
      }
  }
(2)接口

        接口提出了一种规范,让使用接口的程序设计人员必须严格遵守接口的约定。接口可以包含属性、方法、索引器和事件,但不能包含这些成员的具体值,只能进行定义。

        C#声明接口时,使用interface关键字。

       修饰符 interface 接口名称:继承的接口列表

        {

                接口内容:

        }

        1.接口的实现与继承

        定义:

 public interface information
 {
     string Code { get; set; }
     void showInfo();
 }

        实现:

  public class Info : information
  {
      string code = "";
      public string Code
      {
          get
          {
              return code;
          }
          set
          {
              code = value;
          }
      }
      public void showInfo()
      {
          Console.WriteLine(code);
      }
  }

2.显式接口成员实现

        如果类实现两个接口,并且这两个接口包含相同签名的成员,那么在类中实现该成员将导致两个接口都是用该成员作为它们的实现。如果两个接口有不同的功能。会导致其中一个发生错误。这时可以显式实现该接口成员,即创建一个仅通过该接口调用并且特定于该接口的类成员。显式接口的实现是通过使用接口名称和一个句号命名该类成员实现的。示例

 interface information
 {
     string Code { get; set; }
     void showInfo();
 }
 interface information2
 {
     string Code { get; set; }
     void showInfo();
 }

 public class Info : information,information2
 {
     string code = "";
     string information.Code
     {
         get
         {
             return code;
         }
         set
         {
             code = value;
         }
     }
     void information.showInfo()
     {
         Console.WriteLine(code);
     }

     string information2.Code
     {
         get
         {
             return code;
         }
         set
         {
             code = value;
         }
     }
     void information2.showInfo()
     {
         Console.WriteLine(code+"11111");
     }
 }

        调用的时候根据创建的接口调用对应的属性和方法。

(3)集合与索引器

        集合类似于数组,是一组组合在一起的类型化对象,可以通过遍历获取其中的每个元素。例如ArrayList集合是一种非泛型集合类,动态添加删除元素。ArrayList相当于一个高级的动态数组。但并不等同于数组。示例

ArrayList list = new ArrayList();
list.Add("张三");
list.Add("李四");
list.Add("王五");
foreach(string name in list) 
{
    Console.WriteLine(name);
}

        索引器——C#支持一种名为索引器的特殊属性,它能通过引用数组元素的方式来引用对象。

语法:修饰符  类型  this [参数列表]{ get {get 访问器体}    set{set 访问器体} }

示例

 static void Main(string[] args)
 {
     CollClass collClass = new CollClass();
     collClass[0] = "张三";
     collClass[1] = "李四";
     collClass[2] = "王五";

    for(int i=0;i<CollClass.max;i++)
     {
         Console.WriteLine(collClass[i]);
     }
 }

 public class CollClass
 {
     public const int max = 3;
     private string[] arr;
     public CollClass()
     {
         arr = new string[max];
     }
     public string this[int index] //索引器
     {
         get { return arr[index]; }
         set { arr[index] = value; }
     }
 }
(4)委托和匿名方法

        委托是一种引用类型,该引用类型与其他引用类型有所不同,在委托对象的引用中存放的不是对数据的引用,而是委托对方法的引用。(本质上是一种类型安全的函数指针)

        语法:修饰符 delegate 返回类型 委托名称 (参数列表)示例

  public class Test
  {
      public int Add(int x,int y)
          { return x + y; }
  }
  public delegate int add(int x,int y); //创建委托
  static void Main(string[] args)
  {          
      Test test = new Test();
      add a = test.Add;  //创建委托对象
      int num = a(2, 3);
      Console.WriteLine(num);

  }

        匿名方法允许一个与委托关联的代码内联地写入使用委托的位置,这使得代码对于委托的实例很直接。

        语法:delegate(参数列表) {  代码块 } 。示例

  static void Main(string[] args)
  {          
    //  Test test = new Test();
    //  add a = test.Add;
      add b = delegate(int x,int y) { return x + y; };
      int num = b.Invoke(2, 3);
      Console.WriteLine(num);

  }
(5)事件

        1.委托的发布和订阅(有点抽象)

        通过委托实现事件处理的过程,通常有四个步骤:

        (1)定义委托类型,并在发布者类中定义一个该类型的公共成员。

        (2)在订阅者类中定义委托处理方法。

        (3)订阅者对象将事件处理方法链接到发布者对象的委托成员上。

        (4)发布者对象在特定情况下“激发”委托操作,从而自动调用订阅者对象的委托处理方法。

示例:学校打铃,学生执行对应的操作。(根据案例理解)

  public delegate void RingEvent(int ringKand);//参数代表铃声类型 1-上课 2-下课

  public class SchoolRing
  {
      public RingEvent OnBellSound; //委托

      public void Jow(int ringKand) //激发委托
      {
          if (ringKand == 1 || ringKand == 2)
          {
              Console.WriteLine(ringKand == 1 ? "上课铃响了" : "下课铃响了");
              if (OnBellSound != null)
              {
                  OnBellSound(ringKand); 
              }
          }
          else
          {
              Console.WriteLine("参数错误");
          }
      }
  }
  public class Student
  {
      public void SubRing(SchoolRing schoolRing) //订阅委托
      {
          schoolRing.OnBellSound += SchoolJow;
      }
      public void SchoolJow(int ringKand) //委托处理方法
      {
          if (ringKand == 1)
          {
              Console.WriteLine("上课了请学习");
          }
          else if (ringKand == 2)
          {
              Console.WriteLine("下课了请休息");
          }
      }
      public void CancelSub(SchoolRing schoolRing)//取消委托
      {
          schoolRing.OnBellSound-=SchoolJow;
      }
  }


  static void Main(string[] args)
  {          
      SchoolRing schoolRing = new SchoolRing(); //发布者
      Student student = new Student();//订阅者
      student.SubRing(schoolRing); //订阅委托
      Console.Write("请输入参数(1-上课,2-下课):");
      schoolRing.Jow(Convert.ToInt32(Console.ReadLine())); //激发委托
  }

        2.事件的发布和订阅

        事件处理机制,以保证事件订阅的可靠性,其做法是在发布委托的定义中加上event关键字。其他不变。

   public event RingEvent OnBellSound; //委托

        3.EventHandler类

        .NET专门定义了一个EventHandler委托类型,建议使用该类型作为事件的委托类型。

示例 将上边的示例进行修改。

     public delegate void EventHandle(object sender,EventArgs e);//参数代表铃声类型 1-上课 2-下课
    
     public class SchoolRing
     {
         public event EventHandle OnBellSound; //委托

         public void Jow(int ringKand) //激发委托
         {
             if (ringKand == 1 || ringKand == 2)
             {
                 Console.WriteLine(ringKand == 1 ? "上课铃响了" : "下课铃响了");
                 if(OnBellSound!=null)
                 {
                     EventArgs e = new RingEventArgs(ringKand); //实例化参数类
                     OnBellSound(this, e);
                 }
             }
             else
             {
                 Console.WriteLine("参数错误");
             }
         }
     }
     public class Student
     {
         public void SubRing(SchoolRing schoolRing) //订阅委托
         {
             schoolRing.OnBellSound += SchoolJow;
         }
         public void SchoolJow(object sender,EventArgs e) //委托处理方法
         {
             if (((RingEventArgs)e).RingKand == 1)
             {
                 Console.WriteLine("上课了请学习");
             }
             else if (((RingEventArgs)e).RingKand == 2)
             {
                 Console.WriteLine("下课了请休息");
             }
         }
         public void CancelSub(SchoolRing schoolRing)//取消委托
         {
             schoolRing.OnBellSound-=SchoolJow;
         }
     }

     public class RingEventArgs : EventArgs //参数类
     {
         private int ringKand;
         public int RingKand
         {
             get { return ringKand; }
         }
         public RingEventArgs(int ringKand)
         {
             this.ringKand = ringKand;
         }
     }

        2.Window事件

        事件在Windows这样的图形界面程序中很常用,事件响应时程序与用户交互的基础。

(6)迭代器

        更相代替,反复更迭。重复执行统一过程。实现迭代器的接口IEnumerator接口。示例

 public class Family:System.Collections.IEnumerable //将类变为迭代类
 {
     string[] name = { "爸", "妈", "姐", "弟", "哥" };

     public IEnumerator GetEnumerator()
     {
         for (int i = 0; i < name.Length; i++)
         {
             yield return name[i];
         }
     }
 }

 Family family = new Family();

 foreach(string str in family) //对类进行遍历
 {
     richTextBox1.Text += str + "\n";
 }
(7)分部类

        在类的前面加上partial关键字。

注意:分部类必须在同一程序集或同一模块中进行定义。

        分部类在界面开发的优点:每个控件都有生成代码。VS将生成代码放在分部类中。用户就不需要管理这部分代码。只需要专注于逻辑设计即可。

        示例

    private void button1_Click(object sender, EventArgs e)
    {
        Account account = new Account();
        int num1 = Convert.ToInt32(textBox1.Text);
        int num2 = Convert.ToInt32(textBox2.Text);
      
        switch (Convert.ToChar(comboBox1.Text))
        {
            case '+': textBox3.Text  = account.add(num1, num2).ToString(); break;
            case '-': textBox3.Text = account.sub(num1, num2).ToString(); break;
            case '*': textBox3.Text = account.mul(num1, num2).ToString(); break;
            case '/': textBox3.Text = account.div(num1, num2).ToString(); break;
            default:
                break;
        }
    }
}
partial class Account //分部类
{
    public int add(int x, int y)
    {
        return x + y;
    }
}

partial class Account
{
    public int sub(int x, int y)
    {
        return x - y;
    }
}

partial class Account
{
    public int mul(int x, int y)
    {
        return x * y;
    }
}

partial class Account
{
    public int div(int x, int y)
    {
        return x / y;
    }
}
(8)泛型

        1.类型参数T

        可以看做是一个占位符,他不是一种类型,它仅代表某种可能的类型。在定义泛型时,T出现的位置可以使用任意一种类型代替。

        2.泛型接口

        与声明一般接口的唯一区别是增加了一个<T>。一般来说,泛型接口与非泛型接口遵循相同的规则。

        语法:interface 接口名<T>{ 接口体 }

        示例

interface ITest<T>
 {
     T ShowInfo();
 }
 class Test<T, T1> : ITest<T1> where T : T1, new()
 {
     public T1 ShowInfo()
     {
         return new T();
     }
 }

        3.泛型方法

        泛型方法是在声明中包括了参数类型T的方法。

        语法:修饰符 void 方法名 <类型参数 T> {  方法体 }

        示例

  class sale
  {
      public static int sum<T>(T[] items)
      {
          int sum = 0;
          foreach (T item in items)
          {
              sum += Convert.ToInt32(item);
          }
          return sum;
      }
  }

第十三章 文件操作

(1)基本知识

        1.System.IO命名空间

        对文件进行操作时必须要引用的命名空间。

        2.File类

        File类支持对文件的基本操作,包括创建、删除、复制、移动和打开文件的静态方法。由于方法都为静态。使用File类的方法效率比使用对应的FileInfo实例方法可能要高。

        3.FileInfo类

        FileInfo类与File类许多方法调用都是相同的,但FileInfo类没有静态方法,仅可以用于实例化对象。

(2)判断文件是否存在

        File类和FileInfo类都包含判断文件是否存在的方法。

        File类:public static bool Exists(string path);

        FileInfo类:public override bool Exists {get;}

示例

 bool isExits  = File.Exists("D:\\Desktop\\C#\\diedai\\123.txt");

 FileInfo fileInfo = new FileInfo("D:\\Desktop\\C#\\diedai\\123.txt");
  isExits = fileInfo.Exists;
(3)创建文件

         File类:public static FileStream Create(string path);

        FileInfo类:public Filestream Create();

示例

 File.Create("D:\\Desktop\\C#\\diedai\\test.txt");

 FileInfo fileInfo = new FileInfo("D:\\Desktop\\C#\\diedai\\test2.txt");
 fileInfo.Create();
(4)复制文件

        File类:public static void Copy(string sourceFileName,string destFileName);

        FileInfo类:public FileInfo CopyTo(string destFileName);

示例

           File.Copy("D:\\Desktop\\C#\\diedai\\123.txt", "D:\\Desktop\\C#\\diedai\\test.txt");

           string des = "D:\\Desktop\\C#\\diedai\\123.txt";
           FileInfo fileInfo = new FileInfo("D:\\Desktop\\C#\\diedai\\123.txt");
           fileInfo.CopyTo(des);
(5)移动文件

        File类:public static void Move(string sourceFileName,string destFileName);

        FileInfo类:public void MoveTo(string destFileName);

示例

  File.Move("D:\\Desktop\\C#\\diedai\\123.txt", "D:\\Desktop\\C#\\diedai\\test.txt");

  string des = "D:\\Desktop\\C#\\diedai\\123.txt";
  FileInfo fileInfo = new FileInfo("D:\\Desktop\\C#\\diedai\\123.txt");
  fileInfo.MoveTo(des);
(6)删除文件

        File类:public static void Delete(string path);

        FileInfo类:public override void Delete();

示例

File.Delete("D:\\Desktop\\C#\\diedai\\123.txt");      
FileInfo fileInfo = new FileInfo("D:\\Desktop\\C#\\diedai\\123.txt");
fileInfo.Delete();
(7)获取文件信息
 if (openFileDialog1.ShowDialog() == DialogResult.OK) 
 {
     textBox1.Text = openFileDialog1.FileName;

     FileInfo fileInfo = new FileInfo(textBox1.Text);

     string Name = fileInfo.Name; //名称
     string FullName = fileInfo.FullName; //路径
     string CreateTime = fileInfo.CreationTime.ToLongDateString(); //创建时间
     long size = fileInfo.Length;//大小
     bool ReadOnly = fileInfo.IsReadOnly; //只读属性

     MessageBox.Show("名称:" + Name +
         "\n路径:" + FullName +
         "\n创建时间:" + CreateTime +
         "\n大小:" + size +
         "\n只读属性:" + ReadOnly);
 }

        更多关于文件的属性和方法可以参考开发文档。

第十四章 文件夹操作

(1)Directory与DirectoryInfo类

        Directory类主要用于文件夹的基本操作,如移动、复制、重命名、创建和删除等。也可获取目录的相关的属性和信息。是静态类,直接通过类名来调用。

        DirectoryInfo类与Directory类的关系类似于FileInfo类和File类。调用方法需要创建对象。

(2)判断文件夹是否存在

        Directory类:public static bool Exists(String path);

        DirectoryInfo类:public override bool Exists{get;}  

示例

 Directory.Exists("D:\\Desktop\\C#\\diedai");

 DirectoryInfo info = new DirectoryInfo("D:\\Desktop\\C#\\diedai");
 if (info.Exists) { 
 }
(3)创建文件夹    

        Directory类:public static DirectoryInfo CreateDirectory(String path);

        DirectoryInfo类:public void Create()   

        public void Create(DirectorySecurity directorySecurity) //参数是应用此文件夹的访问控制

示例

 Directory.CreateDirectory("D:\\Desktop\\C#\\test");

 DirectoryInfo info = new DirectoryInfo("D:\\Desktop\\C#\\test");

 info.Create();
(4)移动文件夹

        Directory类:public static void Move(string sourceDirName,string destDirName);

        DirectoryInfo类:public void MoveTo(string destDirName);

示例

Directory.Move("D:\\Desktop\\C#\\test", "D:\\Desktop\\test");

DirectoryInfo info = new DirectoryInfo("D:\\Desktop\\C#\\test");

info.MoveTo("D:\\Desktop\\test");

注意,移动文件夹只能在相同根目录下移动。例如,不能从C盘移动到D盘。

(5)删除文件夹

         Directory类:public static void Delete(string path);

        DirectoryInfo类:public void Delete(bool recursive);//如果文件夹下有子文件夹,参数设置是否删除子文件夹。 true删除,false不删除

        public override void Delete();

示例

 Directory.Delete("D:\\Desktop\\C#\\test");

 DirectoryInfo info = new DirectoryInfo("D:\\Desktop\\C#\\test");

 info.Delete();
 //或
 info.Delete(true);
(6)遍历文件夹

        使用DirectoryInfo类。

        GetDirectories()——返回当前目录的子目录。

        GetFiles()——返回当前目录的文件列表。

        GetFileSystemInfos()——返回包含目录中子目录和文件的FileSystemInfo对象的数组。

示例

  listView1.Items.Clear(); //清空列表

  if (folderBrowserDialog1.ShowDialog()==DialogResult.OK) //打开文件对话框
  {
      textBox1.Text = folderBrowserDialog1.SelectedPath; 

      DirectoryInfo info = new DirectoryInfo(textBox1.Text); 

      FileSystemInfo[] fileSystems = info.GetFileSystemInfos(); //获取文件数组

      foreach (var item in fileSystems) //遍历打印文件名和路径
      {
          if (item is DirectoryInfo)
          {
              DirectoryInfo info1 = new DirectoryInfo(item.FullName);
              listView1.Items.Add(info1.Name);
              listView1.Items[listView1.Items.Count-1].SubItems.Add(info1.FullName);
          }
          else
          {
              FileInfo fileInfo = new FileInfo(item.FullName);
              listView1.Items.Add(fileInfo.Name);
              listView1.Items[listView1.Items.Count - 1].SubItems.Add(fileInfo.FullName);
          }
      }
  }

第十五章 流操作类

       .NET FrameWork使用流来支持读取和写入文件,可以将流视为一组连续的一维数组。包括开头和结尾,使用游标指示当前的位置。

(1)流操作

        流中的数据可能来自内存、文件或套接字。流包含几种基本操作:

        1.读取:将数据从流中传输到数据结构。

        2.写入:将数据从数据源传输到流中。

        3.查询:查询和修改在流中的位置。

(2)流的类型

         .NET FrameWork流由Stream类表示,该类构成了其他所有流的抽象类。不能直接构建stream类的实例。但必须由它实现其中的一个类。

        C#中有许多类型的流,但在处理输入和输出时,最重要的流是FileStream类。它提供读取和写入文件的方式。

(3)文件流

        C#中,文件流使用FileStream类表示。一个FileStream类的实例代表了一个磁盘文件,它通过Seek方法进行对文件的随机访问,同时包含了流的标准输入、输出和错误等。默认文件打开方式是同步的,但也支持异步操作。

(4)对文件内容进行操作

        示例:以四种不同方式对文件进行操作。

    FileMode filemode = FileMode.Open;//记录打开的方式
    private void Form1_Load(object sender, EventArgs e)
    {
            if (openFileDialog1.ShowDialog() == DialogResult.OK)
            textBox1.Text = openFileDialog1.FileName.ToString();
    }

    private void button1_Click_1(object sender, EventArgs e)
    {
      
        string path = textBox1.Text;
        try
        {
            using (FileStream fs = File.Open(path, filemode)) //读文件内容
            {
               Byte[] info = new UTF8Encoding(true).GetBytes(textBox2.Text);
               fs.Write(info, 0, info.Length);
                
            }
            using (FileStream fs = File.Open(path, FileMode.Open)) //写文件内容
            {
                byte[] bytes = new byte[1024];
                UTF8Encoding temp = new UTF8Encoding(true);
                string pp = "";
                while (fs.Read(bytes, 0, bytes.Length) > 0)
                {
                    pp += temp.GetString(bytes);
                }
                MessageBox.Show(pp);
            }
        }
        catch
        {
            if (MessageBox.Show("文件不存在,是否创建文件", "提示", MessageBoxButtons.YesNo) == DialogResult.Yes)
            {
                FileStream fs = File.Open(path, FileMode.CreateNew);
                fs.Dispose();
            }
        }
    }

    private void radioButton1_CheckedChanged(object sender, EventArgs e) //读写方式打开
    {
        if (((RadioButton)sender).Checked == true)
        {
               filemode = FileMode.Open;
        }

    }

    private void radioButton2_CheckedChanged(object sender, EventArgs e) //追加方式打开
    {
        if (((RadioButton)sender).Checked == true)
        filemode = FileMode.Append;
    }

    private void radioButton3_CheckedChanged(object sender, EventArgs e) //清空后打开
    {
        if(((RadioButton)sender).Checked == true)
            filemode = FileMode.Truncate;
    }

    private void radioButton4_CheckedChanged(object sender, EventArgs e) //覆盖方式打开
    {
        if (((RadioButton)sender).Checked == true)
            filemode = FileMode.Create;
    }
}
(5)文本文件的读写

        文本文件的写入和读取主要是通过StreamWriter类和StreamReader类来实现的。

        示例 :写文件

 if (!File.Exists("D:\\Desktop\\C#\\Log2.txt"))
 {
     File.Create("D:\\Desktop\\C#\\Log2.txt");
 } 
 string strLog = textBox1.Text + "  "+ DateTime.Now;
 if (textBox1.Text != " " && textBox2.Text != " ")
 {
     using (StreamWriter writer = new StreamWriter("D:\\Desktop\\C#\\Log2.txt", append: true))
     {
         writer.WriteLine(strLog);
     }
     Form2 form2 = new Form2();
     form2.Show();

 }

        读文件

 using (StreamReader reader = new StreamReader("D:\\Desktop\\C#\\Log2.txt", Encoding.UTF8))
 {
     string line = string.Empty;

     string[] split = new string[] { "  " };
     while ((line = reader.ReadLine())!= null)
     {
             string[] strLogs = line.Split(split, StringSplitOptions.RemoveEmptyEntries);
             ListViewItem list = new ListViewItem();
             list.SubItems.Clear();
             list.SubItems[0].Text = strLogs[0];
             list.SubItems.Add(strLogs[1]);
             listView1.Items.Add(list);
         
     }
 }    

        本文内容到此为止,谢谢观看。