当前位置: 首页 > news >正文

NET框架程序设计-第1章.NET框架开发平台体系架构

1.1 .NET 框架基本组成

.NET 框架的核心便是通用语言运行时(Commomn Language Runtime,简称 CLR),CLR 是一个可被各种不同的编程语言所使用的运行时。
托管模块(mangaed module): 一个需要 CLR 才能执行的标准 Windows 可移植可执行(porttable executable ,简称 PE)文件。

将源代码编译为托管模块:
请添加图片描述

表1-1 描述了一个托管模块的各个组成部分
请添加图片描述

托管代码:由于生存期和执行行为受 CLR 管理的缘故,IL 代码有时也称作托管代码
元数据:为托管模块产生完整的元数据。一个数据表的集合。一些用于描述托托管模块中所定义的内容(比如所定义的类型和它们的成员),另外还有一些用于描述托管模块中所引用的内容(比如被引用的类型和它们的成员)。元数据是一些早先的技术如类型库、接口定义语言(IDL)文件的一个超集(CLR 元数据包括但不仅限于列举出来的文件)。

编译器同时产生元数据和 IL 代码,并且总是同时将它们嵌入到生成的托管模块中。

元数据有很多用处,比如:

  • 元数据省去了源代码编译时对头文件和库文件的需求,这是因为在含有实现类型和成员的 IL 代码文件中,已经包含了所有被引用的类型和成员的信息。编译器可以直接从托管模块中读取元数据来获得这些信息。

  • Visual Studio .NET 可以利用元数据来辅助我们编写代码。它的智能感知(IntelliSense)特性就是通过分析元数据来告诉我们某个类型提供了哪些方法,以及某个方法有哪些参数。

  • CLR 的代码验证过程可以利用元数据来确保代码仅执行“安全”的操作

  • 利用元数据,我们可以将一个对象的字段序列化到一个内存块中,然后远程传送给另一台机器,最后再在远程机器上执行反序列化,从而重新创建对象和它的状态

  • 利用元数据,垃圾收集器可以追踪对象的生存期。对于任何对象,垃圾收集器都能够通过元数据来确定该对象的类型,并且可以获知该对象的哪些字段引用了其他对象。

微软的C++ 编译器默认生成的是非托管模块,但可以通过指定一个新的命令行开关,C++ 编译器也能够产生处需要 CLR 才能执行的托管模块。

1.2 将托管模块组合为程序集

CLR 实际上并不和托管模块打交道,它直接打交道的对象是程序集(assembly)。
程序集:一个或多个托管模块,以及一些资源文件的逻辑组合。程序集是组件复用,以及实施安全策略和版本策略的最小单位

图1-2 将托管模块组合为程序集
请添加图片描述

PE 文件(托管模块):包含了一个称作清单(manifest)的数据块。所谓清单仅仅是另外一些元数据表的集合。这些表描述了组成程序集的文件,程序集所有文件中实现的共有导出类型,以及一些和程序集相关的资源文件或数据文件。
托管模块与程序集

  • 仅包含以管模块、并且没有资源(或者数据)文件,程序集就是托管模块。程序集中的模-
  • 块还包含它所引用的程序集的一些信息(如版本号信息)。它不需要再在注册表或者活动目录(Active Directory)中获取额外的信息。因此,程序集的部署要比非托管组件的部署容易得多。

1.3 加载通用语言运行时

判断机器中是否安装了 .NET 框架:

  • 通过在 %windir%\system32 目录下查找 MSCorEE.dll 文件来判断。(…\Windows\System32 目录下)
    判断机器中安装了哪些版本的 .NET 框架:
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\.NETFramewirk\policy

启动应用程序:
当生成一个 EXE 程序集时,编译器/链接器会产生一些特殊的信息,并将它们嵌入到结果程序集的 PE 文件表头及其各个组成文件的 .text 部分。当 EXE 文件被调用时,这些特殊的信息将导致 CLR 被加载并初始化。 CLR 随后会定位到应用程序的入口点方法,从而以此来启动应用程序。

图1-3 加载并初始化 CLR
请添加图片描述

MSCorEE.dll 表示为微软组件对象运行时执行引擎。

托管应用程序启动:
当编译器/链接器创建一个可执行程序集时,x86 stub 函数 JMP CorExeMain 被嵌入到PE文件里。
CorExeMain 函数 从 MsCorEE.dll 动态链接库中导入的,所以 MsCorEE.dll 将在程序集文件的导入==(.idata)==部分被引用。

执行过程:

  • 1、当托管 EXE 文件被调用时,Windows 将像对待通常(即非托管)的 EXE 文件一样来对待它。

  • 2、Windows 加载器首先加载该EXE文件,然后检查其 .idata 部分发现 MSCoreEE.dll 需要被加载到进程的地址空间,于是加载器获取 MSCoreEE.dll 中 __CoreExeMain 函数地址,同时修正托管 EXE 文件中 stub 函数的 JMP 指令

  • 3、进程的主线程开始执行修正后的 x86 stub 函数,该 stub 函数立即跳转到 MSCorEE.dll 中的_CorExeMain 函数上。

  • 4、_CorExeMain 函数接着初始化 CLR,并查看可执行程序集的 CLR 表头以确定要执行的托管入口点方法。

  • 5、入口点方法找到后,其 IL 代码随之被编译为本地 CPU 指令

  • 6、最后,CLR 跳转到编译后的本地指令上(使用进程的主线程)。

  • 7、这时,托管应用程序才算开始真正运行

托管 DLL 执行:
编译器/链接器将会为 DLL 程序集 PE文件的 .text 部分产生一个类似 x86 stub 函数: JMP __CorDllMain。
_CorDllMain 函数 从 MsCorEE.dll 动态链接库中导入的,所以 托管DLL 中的 (.idata)部分 也包含有对MSCorEE.dll 的引用。

执行过程:

  • 1、当 Windows 加载托管 DLL 时,它将自动加载 MSCorEE.dll(如果它还没有被加载)。

  • 2、然后获取 _CorDllMain 函数的地址,并修正托管 DLL 中 x86 stub 函数的 JMP 指令。

  • 3、之后,调用 LoadLibrary 加载托管 DLL 的线程将跳转到该托管 DLL 中的x86 stub 函数上。(非托管代码加载托管 DLL 步骤)
    托管代码调用托管 DLL: 首先检测托管 DLL 中的元数据,然后便以即时编译的方式执行其内方法的 IL 代码,stub 函数及其跳转过程被忽略)

  • 4、该 stub 函数接着又立即跳转到 MSCorEE.dll 中的 _CorDllMain 函数上。

  • 5、_CorDllMain 初始化 CLR(如果 CLR 还没有为该进程初始化)后便立即返回。(非托管代码加载托管 DLL 步骤)

  • 6、应用程序也返回到正常状态并继续运行。

注意:托管 PE 文件总是使用 32 位的 PE 文件格式。在64位的 Windows 系统上,操作系统加载器检测到 32 位的托管 PE 文件后会自动创建64位的地址空间。

1.4 执行程序集代码

IL 代码的作用:理解对象类型,并且拥有很多高级的指令,这些指令可以创建和初始化对象,调用对象上的虚方法,以及直接操作数组元素。它甚至还有抛出和捕获异常的指令。
IL 汇编器:ILAsm.exe
IL 反汇编:ILDasm.exe

即时(just-in-time)编译器执行内容:执行一个方法,它的 IL 代码还必须首先被转换成本地 CPU 指令。

方法的第一次调用:
请添加图片描述

执行过程:

Main函数第一次调用:

  • 1、在 Main 方法执行之前,CLR 首先会检测 Main 中代码引用到的所有类型。这会导致 CLR 分配一个内部的数据结构。该数据结构用于管理对所引用到的类型的访问。(比如为 Console 分配一个单独的内部结构)

  • 2、在这里内部的数据结构中, Console 类型中定义的每一个方法都会有一个对应的条目,每个条目中将保存有一个方法实现代码的地址。

  • 当该数据结构被初始化时,CLR 将==把每一个条目设置为 ==CLR 内部的一个没有正式记录的函数:JITCompiler。

  • 当 Main 方法第一个调用 WriteLine 时, JITCompiler 函数将被调用,该函数负责将一个方法的 IL 代码编译成本地 CPU 指令。因为 IL 代码是被“即时(just-in-time)”编译的,所以 CLR 的这一部分通常被称作 JITter 或者即时编译器。(JIT compiler)

  • 当 JITCompiler 函数被调用时,它会知道正在调用的是哪个方法,以及该方法是由哪个类型定义的。

  • JITCompiler 函数随后会在被调用方法所定义的程序集中的元数据内搜索其 IL 代码的位置

  • JITCompiler 接着验证这些 IL 代码并将编译成本地 CPU 指令。这些本地 CPU 指令将被保存在一个动态分配的内存块中

  • 然后 JITCompiler 将前面内部数据结构中被调用方法的地址替换为包含本地 CPU 指令的内存块地址。

  • 最后 JITCompiler 将跳转到该内存块中的代码上。这里的代码就是 WriteLine 方法的实现代码。当该代码执行完毕,它将返回到 Main 函数中,Main 函数会接着继续执行下面的代码。

Main 函数第二次调用:

  • 1Main 函数开始第二次调用 WriteLine。由于 WriteLine 中的 IL 代码已经被验证并且编译过,所以这一次将直接调用内存块中已有的本地代码,完全跳过 JITCompiler 函数的验证和编译过程。
  • 在 WriteLine 方法执行之后,同样将返回到 Main 中。

请添加图片描述

1.4.1 IL与代码验证

IL 是一种基于堆栈的语言。意味着它的所有指令或者是将操作数推进一个执行堆栈中,或者从堆栈中弹出结果。
IL 指令是无类型的。
当 IL 代码被编译为本地 CPU 指令时,CLR 将执行一个称作验证的过程。验证过程检查高级 IL 代码,确保它做的每件事都是”安全“的。

验证过程可以验证的情况:

  • 不能从未初始化的内存中读取数据;
  • 每个方法调用都必须传入正确的参数个数,并且各个参数的类型要正确匹配;
  • 每个方法的返回值都必须被正确地使用;
  • 每个方法都必须有一个返回语句;

托管代码的好处:

  • 通过验证托管代码,确保它们不会访问它们不应该访问的内存,因此也就不会干扰另一个应用程序的代码。
  • 在一个操作系统进程中运行多个托管应用程序可以减少进程的数量,从而提高系统性能,降低资源需求。

应用程序域: CLR 提供了在一个单独的操作系统进程中执行多个托管应用程序的能力。在 CLR 中,一个托管应用程序称作一个应用程序域。

默认情况下,一个托管 EXE 仅执行在它自己单独拥有的地址空间中(该地址空间中仅含有一个因公用程序域)。到那时,CLR 的宿主进程可以决定在一个操作系统进程中运行多个应用程序域。

1.5 .NET 框架类库

.NET 框架包括 .NET 框架类库(Framework Class Library,简称 FCL)程序集
.NET 应用程序:

  • XML Web 服务: XML Web Services。涉及的内容,HTTP,SOAP,XML,用来
  • Web 窗体:Web Forms。一种基于 HTML的应用程序(Web 站点),涉及的内容,ASP.Net。
  • Windows 窗体:Windows Forms。
  • Windows 控制台应用程序。
  • Windows 服务:由 Windows 服务控制管理器(Service Control Manager,简称 SCM)控制的服务程序。
  • 组件库。
命名空间描述
System其中的类型是为所有应用程序使用的一些基本类型
System.Collection其中的类型用于管理对象集合。包括常用的集合类型,例如堆栈、队列、散列表等
System.Diagnostics其中的类型用于帮助诊断和调试应用程序
System.Drawing其中的类型用于操作二维图形。它们典型地用于 Windows 窗体应用程序,以及创建 Web 窗体页面中显示的图像
System.EnterpriseServices其中的类型用于管理事务、队列组件、对象池、JIT 激活(JIT特指 COM+ 组件服务,即 .NET 内的企业服务中对象的即时激活技术)、安全以及其他一些提高服务器程序中托管代码效能的特性
System.Globalization其中的类型用于多国语言支持(National Language Support,简称 NLS),例如字符串比较、格式化以及日历功能
System.IO其中的类型用于操作 I/O 流、遍历目录和文件
System.Management其中的类型通过 Windows 管理设备(Windows Management Instrumentation,简称 WMI)来管理企业中的计算机
System.Net其中的类型用于网路通信
System.Reflection其中的类型用于查看元数据以及延迟绑定类型和它们的成员
System.Resources其中的类型用于操作外部数据资源
System.Runtime.InteropServices其中的类型允许托管代码访问非托管操作系统平台中的一些功能,如 COM 组件和 Win32 DLL 内的函数
System.Remoting其中的类型用于从远程机器上访问类型
System.Serialization其中的类型用于持久化(persist)对象实例,以及一个流(stream)中重新产生对象实例
System.Security其中的类型用于保护数据和资源
System.Text其中的类型用于以不同的编码方式(如 ASCLL 或者 Unicode)来操作文本
System.Threading其中的类型用于异步操作,以及同步访问资源
System.Xml其中的类型用于处理 XML 模式(schema)和数据
System.Web.Services其中的类型用于创建 XML Web 服务
System.Web.UI其中的类型用于创建 Web 窗体
System.Windows.Forms其中的类型用于创建 Windows GUI 应用程序
System.SeviceProcess其中的类型用于创建由 SCM 控制的 Windows 服务

1.6 通用类型系统

通用类型系统(Common Type System,简称 CTS)来描述类型的定义和行为,包括:字段、方法、属性、事件

CTS还定义了类型可见性和访问类型成员的一些规则,访问控制如下:

  • Private:方法(此处本书只提到方法,但其他成员如字段也是此规则的吧?)只能被同一类型中的其他方法调用。
  • Family:方法可以被派生类型中的代码调用。而不管它们是否位于同一个程序集。(即 protected)
  • Family 与 assembly:方法只可以被位于同一个程序集中的派生类型中的代码调用。IL 汇编语言有这种访问控制,但C# 和其他一些编程语言不支持
  • Assembly:方法可以被同一个程序集中的任何代码调用。(即 internal)
  • Family 或 assembly:方法可以被任何程序集中的派生类型的代码调用,也可以被同一程序集中的任何类型调用。 C# 将之称为 protected internal。
  • Public:方法可以被任何程序集中的任何代码调用。

相关文章:

NET框架程序设计-第1章.NET框架开发平台体系架构

1.1 .NET 框架基本组成 .NET 框架的核心便是通用语言运行时(Commomn Language Runtime,简称 CLR),CLR 是一个可被各种不同的编程语言所使用的运行时。 托管模块(mangaed module): 一个需要 CLR 才能执行的标准 Window…...

(哈希表 ) 349. 两个数组的交集 ——【Leetcode每日一题】

❓349. 两个数组的交集 难度:简单 给定两个数组 nums1 和 nums2 ,返回 它们的交集 。输出结果中的每个元素一定是 唯一 的。我们可以 不考虑输出结果的顺序 。 示例 1: 输入:nums1 [1,2,2,1], nums2 [2,2] 输出:[…...

JavaScript基本语法(二)

JavaScript基本语法 1、变量1.1、简介1.2、变量命名规则1.3、JS的关键字和保留字1.4、声明提升 2、JavaScript数据类型2.1、基本类型2.2、引用类型2.3、两种类型的区别2.4、字符串常用方法 3、数据类型转换 1、变量 1.1、简介 在 JavaScript 中声明一个新变量的方法是使用关键…...

ChatGPT3.5-4资源汇总,直连无梯子

什么是ChatGPT? ChatGPT,全称:聊天生成预训练转换器(英语:Chat Generative Pre-trained Transformer),是OpenAI开发的人工智能聊天机器人程序,于2022年11月推出。该程序使用基于GPT-3.5、GPT-4…...

【Netty】使用 SSL/TLS 加密 Netty 程序(二十)

文章目录 前言一、SSL/TLS概述二、Sslhandler类 前言 回顾Netty系列文章: Netty 概述(一)Netty 架构设计(二)Netty Channel 概述(三)Netty ChannelHandler(四)ChannelP…...

runway gen2

来自Runway文生成视频ai大模型Gen-2_哔哩哔哩_bilibili来自Runway文生成视频ai大模型Gen-2,距离视频制作自由又近了一步。, 视频播放量 1651、弹幕量 0、点赞数 21、投硬币枚数 2、收藏人数 42、转发人数 22, 视频作者 旭升说, 作者简介 一起聊下互联网的那些事&…...

Day2:Windows网络编程-TCP

今天开始进入Windows网络编程的学习,在学习的时候总是陷入Windows复杂的参数,纠结于这些。从老师的讲解中,这些内容属于是定式,主要学习写的逻辑。给自己提个醒,要把精力放在正确的位置,不要无端耗费精力。…...

leetcode1985. 找出数组中的第 K 大整数

给你一个字符串数组 nums 和一个整数 k 。nums 中的每个字符串都表示一个不含前导零的整数。 返回 nums 中表示第 k 大整数的字符串。 注意:重复的数字在统计时会视为不同元素考虑。例如,如果 nums 是 ["1","2","2"]&am…...

基于深度学习的高精度野生动物检测识别系统(PyTorch+Pyside6+YOLOv5模型)

摘要:基于深度学习的高精度野生动物检测(水牛、犀牛、斑马和大象)识别系统可用于日常生活中或野外来检测与定位野生动物目标,利用深度学习算法可实现图片、视频、摄像头等方式的野生动物目标检测识别,另外支持结果可视…...

从零开始 Spring Boot 35:Lombok

从零开始 Spring Boot 35:Lombok 图源:简书 (jianshu.com) Lombok是一个java项目,旨在帮助开发者减少一些“模板代码”。其具体方式是在Java代码生成字节码(class文件)时,根据你添加的相关Lombok注解或类来…...

深入解析Spring源码系列:Day 6 - Spring MVC原理

深入解析Spring源码系列:Day 6 - Spring MVC原理 欢迎来到本系列的第六篇博客。在前几篇博客中,我们探索了Spring框架的核心概念,包括Bean的生命周期、作用域、AOP原理和事务管理。今天,我们将深入研究Spring框架中的MVC&#xf…...

Cmake中message函数 如何优雅地输出

message函数说明 在CMake中&#xff0c;message()函数用于向终端输出信息。 message([<mode>] "message text" ...)函数的<mode>参数可以是以下之一&#xff1a; (none): 等同于STATUS&#xff0c;但不推荐使用。STATUS: 输出的信息会被发送到CMake的…...

人工智能基础部分20-生成对抗网络(GAN)的实现应用

大家好&#xff0c;我是微学AI&#xff0c;今天给大家介绍一下人工智能基础部分20-生成对抗网络(GAN)的实现应用。生成对抗网络是一种由深度学习模型构成的神经网络系统&#xff0c;由一个生成器和一个判别器相互博弈来提升模型的能力。本文将从以下几个方面进行阐述&#xff1…...

JavaScript表单事件(上篇)

目录 一、input: 当表单元素的值发生改变时触发&#xff0c;适用于大多数表单元素。 二、change: 当表单元素的值发生改变且失去焦点时触发&#xff0c;适用于输入框、下拉列表等。 三、submit: 当表单提交时触发&#xff0c;适用于 form 元素。 四、reset: 当表单重置时触…...

vb6 Webview2微软Edge Chromium内核执行JS取网页数据测速

微软Edge Chromium内核执行JS获取网页数据测试 ExcuteScript eval(document.body.innerHTML) from : https://www.163.com 采集的网页HTM字符串占用字节空间1.2MB ExcuteScript回调事件中取得JS执行结果&#xff0c;用时 54 毫秒 其中JSON转字符13.5209毫秒 jSON数据长度: 增…...

编码,Part 1:ASCII、汉字及 Unicode 标准

个人博客 编码的历史由来就懒得介绍了&#xff0c;只需要知道人类处理文本信息是以字符为基本单位&#xff0c;而计算机在最底层只认识 0/1&#xff0c;所以当计算机要为人类存储/呈现字符时&#xff0c;就需要有一个规则&#xff0c;在字符和 0/1 序列之间建立映射关系&#…...

C++ Eigen库矩阵操作

C Eigen库 序号功能例子1赋值Eigen::MatrixXf mat (12,1); \\% mat << 1, 2, 3, 4,5,6,7,8,9,10,11,12;2Inplace操作 \\% resizemat.resize(4, 3); \\% 1 5 9 \\% 2 6 10 \\% 3 7 11 \\% 4 8 123转置 \\% transposeInPlacemat.transposeInPlace(); \\% 1 2 3 4 \\% 5…...

Linux-0.11 boot目录bootsect.s详解

Linux-0.11 boot目录bootsect.s详解 模块简介 bootsect.s是磁盘启动的引导程序&#xff0c;其概括起来就是代码的搬运工&#xff0c;将代码搬到合适的位置。下图是对搬运过程的概括&#xff0c;可以有个印象&#xff0c;后面将详细讲解。 bootsect.s主要做了如下的三件事: 搬…...

django组件552

前言&#xff1a;相信看到这篇文章的小伙伴都或多或少有一些编程基础&#xff0c;懂得一些linux的基本命令了吧&#xff0c;本篇文章将带领大家服务器如何部署一个使用django框架开发的一个网站进行云服务器端的部署。 文章使用到的的工具 Python&#xff1a;一种编程语言&…...

【枚举算法的Java实现及其应用】

文章目录 枚举算法概述枚举算法的实现步骤Java实现枚举算法枚举算法的底层工作原理枚举算法的底层代码讲解枚举算法的实际应用场景枚举算法在场景中解决的问题总结 枚举算法概述 枚举算法是一种通过列举所有可能情况来解决问题的方法。这种算法在解决一些特定类型的问题时非常…...

linux led 驱动

前言 今天是儿童节&#xff0c;挣个奖牌给小孩玩玩。 在 linux 驱动大家庭中&#xff0c;LED 驱动算是个儿童&#xff0c;今天就写写他吧。正好之前写过他的婴儿时期《i.MX6ULL 裸机点亮 LED》&#xff0c;记得那时候他还穿着开裆裤呢&#xff0c;裸鸡嘛。 ioremap() 裸机程…...

平面最近点对(分治算法)

文章目录 平面最近点对&#xff08;分治算法&#xff09;Solution流程完整模板代码 平面最近点对&#xff08;分治算法&#xff09; 文章首发于我的个人博客&#xff1a;欢迎大佬们来逛逛 平面最近点对&#xff08;加强版&#xff09; - 洛谷 给你一些点&#xff0c;求两点之…...

【基于前后端分离的博客系统】Servlet版本

&#x1f389;&#x1f389;&#x1f389;点进来你就是我的人了博主主页&#xff1a;&#x1f648;&#x1f648;&#x1f648;戳一戳,欢迎大佬指点! 欢迎志同道合的朋友一起加油喔&#x1f93a;&#x1f93a;&#x1f93a; 目录 一. 项目简介 1. 项目背景 2. 项目用到的技…...

在线Excel绝配:SpreadJS 16.1.1+GcExcel 6.1.1 Crack

前端&#xff1a;SpreadJS 16.1.1 后端&#xff1a; GcExcel 6.1.1 全能 SpreadJS 16.1.1此版本的产品中包含以下功能和增强功能。 添加了各种输入掩码样式选项。 添加了在保护工作表时设置密码以及在取消保护时验证密码的支持。 增强了组合图以将其显示为仪表图。 添加了…...

一个轻量的登录鉴权工具Sa-Token 集成SpringBoot简要步骤

Sa-Token 集成SpringBoot简要步骤 1.1 简单介绍 Sa-Token是一个轻量级Java权限认证框架。 主要解决的问题如下&#xff1a; 登录认证 权限认证 单点登录 OAuth2.0 分布式Session会话 微服务网关鉴权等一系列权限相关问题。 1.2 登录认证 设计思路 对于一些登录之后…...

day 44 完全背包:518. 零钱兑换 II;377. 组合总和 Ⅳ

完全背包&#xff1a;物品可以使用多次 完全背包1. 与01背包区别 518. 零钱兑换 II1. dp数组以及下标名义2. 递归公式3. dp数组如何初始化4. 遍历顺序:不能颠倒两个for循环顺序5. 代码 377. 组合总和 Ⅳ:与零钱兑换类似&#xff0c;但是是求组合数1. dp数组以及下标名义2. 递归…...

K8s in Action 阅读笔记——【5】Services: enabling clients to discover and talk to pods

K8s in Action 阅读笔记——【5】Services: enabling clients to discover and talk to pods 你已了解Pod以及如何通过ReplicaSets等资源部署它们以确保持续运行。虽然某些Pod可以独立完成工作&#xff0c;但现今许多应用程序需要响应外部请求。例如&#xff0c;在微服务的情况…...

牛客网DAY2(编程题)

圣诞节来啦&#xff01;请用CSS给你的朋友们制作一颗圣诞树吧~这颗圣诞树描述起来是这样的&#xff1a; 1. "topbranch"是圣诞树的上枝叶&#xff0c;该上枝叶仅通过边框属性、左浮动、左外边距即可实现。边框的属性依次是&#xff1a;宽度为100px、是直线、颜色为gr…...

Java经典笔试题—day14

Java经典笔试题—day14 &#x1f50e;选择题&#x1f50e;编程题&#x1f36d;计算日期到天数转换&#x1f36d;幸运的袋子 &#x1f50e;结尾 &#x1f50e;选择题 (1)定义学生、教师和课程的关系模式 S (S#,Sn,Sd,Dc,SA &#xff09;&#xff08;其属性分别为学号、姓名、所…...

一个帮助写autoprefixer配置的网站

前端需要用到postcss的工具&#xff0c;用到一个插件叫autoprefixer&#xff0c;这个插件能够给css属性加上前缀&#xff0c;进行一些兼容的工作。 如何安装之类的问题在csdn上搜一下都能找到&#xff08;注意&#xff0c;vite是包含postcss的&#xff0c;不用在项目中安装pos…...