C#学习笔记

记录一下C#的学习过程,对于习惯了C语言的人来说上手还是困难

https://www.cjavapy.com/article/1852/

在C# 的语言中,方法相当于其它语言中的函数,但是它与传统的函数也有着明确的不同:在结构化的语言中,整个程序是由一个个函数组成的;但是在面向对象的语言里,整个程序是由一个个类组成的。因此在C# 中,方法不能独立存在,它只能属于类或者对象。因此,如果我们要定义一个方法,就必须在类中定义。值得注意的是,如果这个方法添加了修饰符static,这个方法就属于这个类,否则的话,这个方法属于这个类的实例。方法是仅在调用时运行的代码块。可以将称为参数的数据传递到方法中。方法主要是能重用代码,定义一次代码,并多次使用。

方法 = 函数

如果这个方法添加了修饰符static这个方法就属于这个类,否则这个方法数据之类的实例。

重载

只要参数的数量或类型不同,多个方法就可以具有相同的名称。

类是对象的模板,而对象是类的实例

C# 面向对象编程有三大特性,它们是封装、继承和多态。

封装:

将类封装起来,只提供想提供的方法接口,而不需要提供具体实现细节,这样一来使得程序更加健壮。 另一方面比方说项目做到一半换人了,需要修改代码,有了封装之后,你完全不用管前人写的烂代码,只需要给出必须的接口方法,就可以自己写自己的了,修改方便。

继承:

继承很明显就是从一个已有的类那得到一些东西,能够很好的实现代码的重用性。被继承的类称之为父类或者超类,继承父类的类称为子类。C# 中所有类都是Object类的子类。另外C#中只允许单继承,这样一来避免了多继承带来的代码过度耦合的问题。虽然不能多继承,但是C#中可以实现多个接口,来实现功能的扩展。

多态:

指的是子类对象可以赋值给父类变量,但运行是仍表现出子类的行为特征,这意味着同一个类型的对象在执行同一个方法时,可以表现出多种行为特征。简单来说,就是程序中同名的不同方法。

定义声明类

public class MyClass

{ int x = 5; }

定义声明对象

namespace ConsoleApplication { public class MyClass { int x = 5; public static void Main(string[] args) { MyClass myObj = new MyClass(); Console.WriteLine(myObj.x); } } }

namespace ConsoleApplication
{
    public class MyClass
    {
        // Static 方法
        static void MyStaticMethod()
        {
            Console.WriteLine("可以在不创建对象的情况下调用静态方法");
        }
        // Public 方法
        public void MyPublicMethod()
        {
            Console.WriteLine("公共方法必须通过创建对象来调用");
        }
        // Main 方法
        public static void Main(string[] args)
        {
            MyStaticMethod(); // 调用静态方法
                              // myPublicMethod(); 这个编译会报错
            MyClass myObj = new MyClass(); // 创建一个MyClass的对象
            myObj.MyPublicMethod(); // 调用对象的公共方法
        }
    }
}

构造函数

C# 中的构造函数是一种用于初始化对象的特殊方法。 创建类的对象时将调用构造函数。 可用于设置对象属性的初始值:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace ConsoleApplication
{
    // 定义MainClass类
    public class MainClass
    {
        int x;  // 创建一个类属性
        // 为Main类创建一个类构造函数
        public MainClass()
        {
            x = 5;  // 为类属性x设置初始值
        }
        public static void Main(string[] args)
        {
            MainClass myObj = new MainClass(); // 创建Main类的对象(这将调用构造函数)
            Console.WriteLine(myObj.x); // 输出x的值
        }
    }
}// 输出 5

构造函数名称必须匹配类名称,并且不能具有返回类型(例如,void)。 另外注意,在创建对象时会调用构造函数。默认情况下,所有类都具有构造函数:如果未创建类构造函数,则C# 会为创建一个。 但是将无法设置对象属性的初始值。

可以有入参但是返回值必须是void

C#修饰符

C# 修饰符-CJavaPy

封装

C# 是面向对象的编程语言,对象就是面向对象程序设计的核心。所谓对象就是真实世界中的实体,对象与实体是一一对应的,也就是说现实世界中每一个实体都是一个对象,它是一种具体的概念。C# 面向对象编程有三大特性,它们是封装、继承和多态。本文主要介绍C# 封装。

封装可以隐藏实现的细节,让使用者只能通过实现写好的访问方法来访问这些字段,这样一来我们只需要在这些方法中增加逻辑控制,限制对数据的不合理访问。方便数据检查,有利于于保护对象信息的完整性。便于修改,提高代码的可维护性。实现良好的封装,需要从两个方面考虑:

  1. 把字段(成员变量)和实现细节隐藏起来,不允许外部直接访问
  2. 把方法暴露出来,让方法控制这些成员变量进行安全的访问和操作

所以,封装的含义是确保对用户隐藏敏感数据。为此,必须:

  • 将类变量/属性声明为private
  • 提供公共的get和set方法来访问和更新private变量的值

C# 命名空间(namespace)

System:处理内建数据、数学计算、随机数的产生、环境变量、垃圾回收器及一些常见的异常和特征。

System.Collections:包含了一些与集合相关的类型,比如列表、队列、位数组、哈希表和字典等。

System.Collections.Generic:定义泛型集合的接口和类,泛型集合允许用户创建强类型集合,它能提供更好的类型安全性和性能。

System.IO:包含了一些数据流类型并提供了文件和目录同步异步读写。

System.IO.Comoression:提供基本的流压缩和解压缩服务的类。

System.IO.Ports:控制串行端口的类。

System.Text:包含了一些表示字符编码的类型并提供了字符串的操作和格式化。

System.Reflection:包括了一些提供加载类型,方法和字段的托管视图以及动态创建和调用类型功能的类型。

System.Threading:提供启用多线程的类和接口。

System.Runtime.InteropServices:使得.NET类型可以与非托管代码交互。

2)图形命名空间

System.Drawing:这个主要的GDI+命名空间定义了许多类型,实现基本的绘图类型(字体,钢笔,基本画笔等)和无所不能的Graphics对象。

System.Drawing2D:这个命名空间提供高级的二维和失量图像功能。

System.Drawing.Imaging:这个命名空间定义了一些类型实现图形图像的操作。

System.Drawing.Text:这个命名空间提供了操作字体集合的功能。

System.Drawing.Printing:这个命名空间定义了一些类型实现在打印纸上绘制图像,和打印机交互以及格式化某个打印任务的总体外观等功能。

3)语言集成查询

System.Linq:支持使用语言集成查询的查询。

System.Xml.Linq:包含LINQtoXML的类。

System.Data.Linq:包含支持与LINQtoSQL应用程序中的关系数据库进行交互的类。

3、使用using引入namespace(命名空间)
有很多基础的类库可供选择。在前面的示例中,我们使用了System命名空间中的Console类。该命名空间还包含数学计算、随机数的产生、环境变量、垃圾回收器及其他实用程序类。

引用入命令名空间,需要使用using关键字:

继承

C# 继承 (子类 和 基类)

在C# 中,可以将属性和方法从一个类继承到另一个类。 继承分为两类:

  • 子类(子类):从另一个类继承的类
  • 基类(父级):继承自的类

student是从people继承过来的,所以stdudent就有了Study();方法

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace ConsoleApplication
{
  public class People
  {
    protected string Name = "cjavapy";        // People 属性
    public void Study()
     {                    // People 方法
      Console.WriteLine("好好学习");
     }
  }
  public class Student : People
  {
    private string className = "Python";    // Student 属性
    public static void Main(string[] args)
    {
    // 创建 student 对象
    Student student = new Student();
    // 调用student的study() 方法 (从 People 类继承) student 
    student.Study();
    // 显示Name属性(从 People 类继承)的值和Student类的className的值
    Console.WriteLine(student.Name + " " + student.className);
    }
  }
}

sealed 关键字

如果不希望其他类继承自一个类,请使用sealed 关键字:

如果尝试访问sealed 类,则C#将生成错误:

sealed class People {
...
}
class Student: People {
...
}

多态

继承使我们可以从另一个类继承属性和方法。多态使用这些方法来执行不同的任务。这使我们能够以不同的方式执行单个方法。

1)引用的多态

父类的引用可以指向本类的对象,父类的引用可以指向子类的对象。

注意:子类的对象不可以指向父类的对象

2)方法的多态

创建本类对象时,调用的方法为本类的方法。创建子类对象时,调用的方法为子类重写的方法或者继承的方法。

注意:父类的引用调用的方法不能是子类独有的方法,必须是从父类继承的方法或重写父类的方法。

以下方法实现了eat方法的多态

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace ConsoleApplication
{
    class Program
    {
        static void Main(string[] args)
        {
            Animal myAnimal = new Animal();  // 创建 Animal 对象
            Animal myCat = new Cat();  // 创建 Cat 对象
            Animal myDog = new Dog();  // 创建 Dog 对象
            myAnimal.Eat();
            myCat.Eat();
            myDog.Eat();
            Console.ReadKey();
        }
    }
    class Animal
    {
        public virtual void Eat()
        {
            Console.WriteLine("吃饭");
        }
    }
    class Cat : Animal
    {
        public override void Eat()
        {
            Console.WriteLine("吃鱼");
        }
        public void CatchMouse()
        {
            Console.WriteLine("抓老鼠");
        }
    }
    class Dog : Animal
    {
        public override void Eat()
        {
            Console.WriteLine("吃骨头");
        }
        public void KanJia()
        {
            Console.WriteLine("看家");
        }
    }
}

C# 面向对象 抽象类、抽象属性和抽象方法

在类的继承中,如果一个个新的子类被定义,子类变得越来越具体,父类变得更加一般和通用,类的设计应该保证父子类能够共享特征,有时将父类设计得非常抽象,使得父类没有具体的实现,这样的类叫做抽象类;一般当我们设计一个类,不需要创建此类的实例时,可以考虑将该类设置成抽象类,让其子类实现这个类的抽象方法。C#允许把类、属性和函数声明为abstract。抽象类不能实例化,抽象类可以包含普通属性和抽象属性,普通函数和抽象函数。抽象函数就是只有函数定义没有函数体的函数。显然,抽象函数本身也是虚拟(virtual)的。

C# 面向对象 接口(interface)和虚方法(virtual)

1、C# 接口(interface)

在C#中实现抽象的另一种方法是使用接口(interface)。接口(interface)是抽象方法和常量值的定义的集合。从本质上讲,接口是一种特殊的抽象类,这种抽象类中只包含常量和方法的定义,而没有变量和方法的实现。有时必须从几个类中派生出一个子类,继承它们所有的属性和方法。但是,C#不支持多重继承。有了接口,就可以得到多重继承的效果。下面看一下接口使用示例。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace cjavapy
{
    // Interface
    interface Animal
    {
        void Eat();   // 接口方法(没有实现)
        void Sleep(); // 接口方法(没有实现)
    }
    // Cat 实现 Animal 接口
    class Cat : Animal
    {
        public void Eat()
        {
            // 这里提供了eat()的实现
            Console.WriteLine("吃鱼");
        }
        public void Sleep()
        {
            // 这里提供了sleep()的实现
            Console.WriteLine("Zzz");
        }
    }
    class Program
    {
        static void Main(string[] args)
        {
            Cat myCat = new Cat();  // 创建Cat对象
            myCat.Eat();
            myCat.Sleep();
        }
    }
}

实现多个接口

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace cjavapy
{
    interface FirstInterface
    {
        void MyMethod(); // 接口方法
    }
    interface SecondInterface
    {
        void MyOtherMethod(); // 接口方法
    }
    class DemoClass : FirstInterface, SecondInterface
    {
        public void MyMethod()
        {
            Console.WriteLine("myMethod");
        }
        public void MyOtherMethod()
        {
            Console.WriteLine("myOtherMethod");
        }
    }
    class Program
    {
        static void Main(string[] args)
        {
            DemoClass myObj = new DemoClass();
            myObj.MyMethod();
            myObj.MyOtherMethod();
        }
    }
}

虚方法

virtual 关键字用于修饰方法或属性的声明,方法或属性被称作虚拟成员。虚拟成员的实现可由派生类中的重写实现。相对于接口,虚方法可以不被重写,定义方法时能够有自己的方法体。虚方法默认是有实现的。例用示例如下,

using System;
namespace VirtualMethodTest
{
    class BaseAnimal
    {
        public virtual void Func() // 注意virtual,表明这是一个虚方法
        {
            Console.WriteLine("I am baseAnimal");
        }
    }
    class Animal: BaseAnimal 
    {
        public override void Func() // 注意override ,表明重新实现了虚函数
        {
            Console.WriteLine("I am Animal");
        }
    }
    class Cat : Animal
    {
    }
    class Dog : BaseAnimal 
    {
        public new void Func() // 注意new ,表明覆盖父类里的同名方法,而不是重新实现
        {
            Console.WriteLine("I am Dog");
        }
    }
    class program
    {
        static void Main()
        {
            BaseAnimal a;         
            BaseAnimal b;       
            BaseAnimal c;  
            BaseAnimal d; 
            a = new BaseAnimal(); 
            b = new Animal();
            c = new Cat(); 
            d = new Dog(); 
            a.Func();    
            b.Func();    
            c.Func(); 
            d.Func();    
            Dog d1 = new Dog();
            d1.Func(); 
            Console.ReadLine();
        }
    }
}
4、虚方法与接口的区别
虚方法与抽象方法都能被重写,抽象方法只能存在于抽象类中,虚方法既可以存在于抽象类中,也可以存在非抽象类中。继承虚方法的类可以重写虚方法也可以选择不重写虚方法,但是抽象方法必须要重写,不然编译会报错。抽象方法是虚方法的一种特殊情况,他的特点在于定了一个规则,他的子类必须遵循这一规则。抽象类运用场景一般在于一个方法是流程里面必要的方法,但是这个方法根据具体情况有多重不一样的实现方法,此时就可以用抽象方法。

5、抽象类与接口的区别
抽象方法与接口都是定义了一种规则,继承他们的类都必须遵循这一规则。抽象类也是类,类所有的特性他都有,接口则不然。抽象类里面可以有非抽象成员,但是接口里面只能有抽象成员,所有成员默认是abstract,类实现继承的时候最多只能继承一个类(抽象类、非抽象类)但是可以继承多个接口。

C# 特性标签(Attribute)

1、特性(Attribute)

使用特性,可以有效地将元数据或声明性信息与代码(程序集、类型、方法、属性等)相关联。 将特性与程序实体相关联后,可以在运行时使用 反射 这项技术查询特性。

特性具有以下属性:

1)特性向程序添加元数据。 元数据 是程序中定义的类型的相关信息。 所有 .NET 程序集都包含一组指定的元数据,用于描述程序集中定义的类型和类型成员。 可以添加自定义特性来指定所需的其他任何信息。

2)可以将一个或多个特性应用于整个程序集、模块或较小的程序元素(如类和属性)。

3)特性可以像方法和属性一样接受自变量。

4)程序可使用反射来检查自己的元数据或其他程序中的元数据。

.NET(C#) 中的程序集

程序集构成了 .NET 应用程序的部署、版本控制、重用、激活范围和安全权限的基本单元。 程序集是为协同工作而生成的类型和资源的集合,这些类型和资源构成了一个逻辑功能单元。 程序集采用可执行文件 (.exe) 或动态链接库文件 (.dll) 的形式,是 .NET 应用程序的构建基块 。 它们向公共语言运行时提供了注意类型实现代码所需的信息。本文主要介绍.NET 中的程序集。

1、程序集(.NET Core和C#)

在 .NET Core 和 .NET Framework 中,可以从一个或多个源代码文件生成程序集。 在 .NET Framework 中,程序集可以包含一个或多个模块。 因此,大型项目可以采用以下规划:由多个开发者单独开发各源代码文件或模块,最后整合所有这些内容以创建一个程序集。

程序集具有以下属性:

1)程序集以 .exe 或 .dll 文件的形式实现 。

2)对于面向 .NET Framework 的库,可以通过将程序集放入全局程序集缓存 (GAC),在应用程序之间共享程序集。 必须先对程序集进行强命名,然后才能将它们包含到 GAC 中。

3)只有在需要使用时才会将程序集加载到内存中。 如果未使用程序集,则不加载。 也就是说,使用程序集,可以在大型项目中高效管理资源。

4)可以使用反射,以编程方式获取程序集的相关信息。

5)你可以加载一个程序集,以使用 .NET Core 中的 MetadataLoadContext 类以及 .NET Core 和 .NET Framework 中的 Assembly.ReflectionOnlyLoad 或 Assembly.ReflectionOnlyLoadFrom 方法来检查该程序集。

2、公共语言运行时中的程序集

程序集向公共语言运行时提供了注意类型实现代码所需的信息。 对于运行时,类型不存在于程序集上下文之外。

程序集定义以下信息:

1)公共语言运行时执行的代码。 请注意,每个程序集只能有一个入口点:DllMain、WinMain 或 Main。

2)安全边界。 程序集就是在其中请求和授予权限的单元。

3)类型边界。 每一类型的标识均包括该类型所驻留的程序集的名称。 在一个程序集的范围中加载的称为 MyType 的类型不同于在另一个程序集范围中加载的称为 MyType 的类型。

4)引用范围边界。 程序集清单包含用于解析类型和满足资源请求的元数据。 该清单指定要在程序集外公开的类型和资源,并枚举它所依赖的其他程序集。 除非可迁移可执行 (PE) 文件中的 Microsoft 中间语言 (MSIL) 代码具有相关的程序集清单,否则不执行此代码。

5)版本边界。 程序集是公共语言运行时中无版本冲突的最小单元。 同一程序集中的所有类型和资源均会被版本化为一个单元。 程序集清单描述你为任何依赖项程序集所指定的版本依赖性。

6)部署单元。 当一个应用程序启动时,只有该应用程序最初调用的程序集必须存在。 其他程序集(例如,包含本地化资源或实用工具类的程序集)可以按需检索。 这样,应用在第一次下载时就会比较精简。

7)并行执行单元。

3、创建程序集

程序集可以为静态或动态。 静态程序集存储在磁盘上的可迁移可执行 (PE) 文件中。 静态程序集可以包括接口、类和资源(如位图、JPEG 文件和其他资源文件)。 你还可以创建动态程序集,动态程序集直接从内存运行并且在执行前不保存到磁盘上。 你可以在执行动态程序集后将它们保存在磁盘上。

有几种创建程序集的方法。 你可以使用可创建 .dll 或 .exe 文件的开发工具,例如 Visual Studio 。 可以使用 Windows SDK 中的工具创建具有从其他开发环境中创建的模块的程序集。 还可以使用公共语言运行时 API(例如 System.Reflection.Emit)来创建动态程序集。

可以采用以下方法编译程序集:在 Visual Studio 中生成程序集、使用 .NET Core 命令行接口工具生成程序集,或使用命令行编译器生成 .NET Framework 程序集。

注意:若要在 Visual Studio 中生成程序集,请在“生成”菜单上选择“生成” 。

4、程序集清单

每个程序集都有一个程序集清单文件。 与目录类似,程序集清单包含以下内容:

1)程序集的标识(名称和版本)。

2)文件表,描述构成程序集的其他所有文件(例如,.exe 或 .dll 文件所依赖的你创建的其他程序集、位图文件或自述文件) 。

3)程序集引用列表,即所有外部依赖项的列表,如 .dll 或其他文件 。 程序集既可以引用全局对象,也可以引用私有对象。 全局对象可用于所有其他应用程序。 在 .NET Core 中,全局对象与特定的 .NET Core 运行时结合使用。 在 .NET Framework 中,全局对象位于全局程序集缓存 (GAC) 中。 System.IO.dll 是 GAC 中程序集的一个示例。 私有对象必须位于级别不高于应用安装目录的目录中。

由于程序集包含内容、版本控制和依赖项的相关信息,因此使用它们的应用程序不依赖 Windows 系统上的注册表等外部源也能正常运行。 程序集减少了 .dll 冲突,让应用程序变得更可靠、更易于部署。 在许多情况下,只需将 .NET 应用程序的文件复制到目标计算机,即可进行安装。

5、引用程序集

必须添加对应用程序中的程序集的引用,才能使用该程序集。 引用程序集后,应用程序可以使用其名称空间的所有可访问类型、属性、方法和其他成员,就好像它们的代码是源文件的一部分一样。

注意:.NET 类库中的大多数程序集都是自动引用的。 如果系统程序集不是自动引用的,则对于 .NET Core,可以添加对包含该程序集的 NuGet 包的引用。 请使用 Visual Studio 中的 NuGet 包管理器,或者将程序集的 <PackageReference> 元素添加到 .csproj 或 .vbproj 项目 。 在 .NET Framework 中,可以通过在 Visual Studio 中使用“添加引用”对话框,或者通过使用 C# 或 Visual Basic 编译器的-reference 命令行选项,添加对该程序集的引用。

官方文档Assemblies in .NET | Microsoft Learn

C#中的GET SET

C#中“public string Name { get; set; }”什么意思?_public bool newstate { get; set; }_阿尔兹的博客-CSDN博客

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值