【C# Programming】值类型、良构类型

值类型

1、值类型

        值类型的变量直接包含值。换言之, 变量引用的位置就是值内存中实际存储的位置。

2、引用类型

        引用类型的变量存储的是对一个对象实例的引用(通常为内存地址)。

        复制引用类型的值时,复制的只是引用。这个引用非常小(32位机器时4 字节引用)

3、结构

        除string 和object 是引用类型,所有C# 内建类型都是值类型。C#也 允许用户自定义值类型。

        结构是一种自定义的值类型,它使用关键字struct。 例如:

struct Angle
{public Angle(int degrees, int minutes, int seconds){Degrees = degrees;Minutes = minutes;Seconds = seconds;}// Using C# 6.0 read-only, automatically implememted properties.public int Degrees { get; }public int Minutes { get; }public int Seconds { get; }public Angle Move(int degrees, int minutes, int seconds){return new Angle(Degrees + degrees, Minutes + minutes, Seconds + seconds);}
}
3.1 结构的初始化
  • 除了属性和字段,结构还可包含方法和构造器。结构不允许包含用户定义的默认构造器。在没有提供默认的构造器时, C# 编译器会自动生成一个默认构造器将所有字段初始化为各自的默认值。
  • 为了确保值类型的局部变量能完全初始化,结构的每个构造器都必须初始化结构中所有字段。如果对结构的所有数据初始化失败,会造成编译错误。  
  • C# 禁止结构中的字段初始化器,例如:
struct Angle 
{//……// ERROR:  Fields cannot be initialized at declaration time// private int _Degrees = 42;
}
  • 为值类型使用new 操作符,会造成“运行时”在临时存储池中创建对象的新实例,并将所有字段初始化为默认值。

4、default 操作符的使用

        所有值类型都有自定义的无参构造器将值类型的实例初始化成默认状态。所以总可以合法使用new操作符创建值类型的变量。除此之外,还可使用default操作符生成结构的默认值。例如: 

struct Angle
{public Angle(int hours, int minutes): this(hours, minutes, default(int)) {}public Angle(int degrees, int minutes, int seconds){Degrees = degrees;Minutes = minutes;Seconds = seconds;}public int Degrees { get; }public int Minutes { get; }public int Seconds { get; }public Angle Move(int degrees, int minutes, int seconds){return new Angle(Degrees + degrees, Minutes + minutes, Seconds + seconds);}
}

5、值类型的继承和接口

  • 所有值类型都隐式密封
  • 除枚举外,所有值类型都派生自 System.ValueType
  • 值类型也能实现接口

6、装箱

6.1 将值类型转换为一个引用类型称为装箱(boxing) 转换。 转换的结果时对一个存储位置的引用。

转换的步骤如下:

  • 在堆上分配内存, 它将用于存放值类型数据以及少许额外开销。  
  • 接着发生一次内存复制,当前存储位置的值类型数据被复制到堆上分配好的位置。
  • 转换的结果是对堆上新存储位置的引用  
6.2 相反的过程称为拆箱(unboxing).拆箱转换先检查已经装箱的值的类型兼容于要拆箱成的值类型,然后复制堆中存储的值
6.3 装箱/拆箱的CIL 代码

6.4 如果装箱和拆箱进行的不是很频繁,那么实现它们的性能问题不大。但有的时候,装箱会频繁发生,这就可能大幅影响性能。例如:
static void Main()
{int totalCount;System.Collections.ArrayList list = new System.Collections.ArrayList();Console.Write("Enter a number between 2 and 1000:");totalCount = int.Parse(Console.ReadLine());// Execution-time error:// list.Add(0);  // Cast to double or 'D' suffix required. Whether cast or using 'D' suffix, list.Add((double)0);  // boxinglist.Add((double)1);  // boxingfor(int count = 2; count < totalCount; count++){list.Add(((double)list[count - 1] +    // unboxing(double)list[count - 2]));    // unboxing}foreach(double count in list)   // unboxing Console.Write("{0}, ", count);//boxing
}  
6.5 另一个装箱/拆箱例子 (接口要求被调用者为引用类型):
class Program 
{static void  Main(){Angle angle = new Angle(25, 58, 23);object objectAngle = angle;  // BoxConsole.Write(((Angle)objectAngle).Degrees);((Angle)objectAngle).MoveTo(26, 58, 23);   // Unbox, modify unboxed value, and discard valueConsole.Write(", " + ((Angle)objectAngle).Degrees);((IAngle)angle).MoveTo(26, 58, 23);     // Box, modify boxed value, and discard reference to boxConsole.Write(", " + ((Angle)angle).Degrees);((IAngle)objectAngle).MoveTo(26, 58, 23);    // Modify boxed value directlyConsole.WriteLine(", " + ((Angle)objectAngle).Degrees);}
}
interface IAngle 
{void MoveTo(int hours, int minutes, int seconds);
}
struct Angle : IAngle 
{public Angle(int degrees, int minutes, int seconds) {Degrees = degrees;Minutes = minutes;Seconds = seconds;}// NOTE:  This makes Angle mutable, against the general guidelinepublic void MoveTo(int degrees, int minutes, int seconds) {Degrees = degrees;Minutes = minutes;Seconds = seconds;}public int Degrees {get; set;}public int Minutes {get; set;}public int Seconds {get; set;}
}
6.6 如果将值类型的实例作为接收者来调用object 声明的虚方法时
  • 如果接收者已拆箱,而且结构重写了该方法,将直接调用重写的方法。因为所有值类型都是密封的。
  • 如果接收者已拆箱,而且结构没有重写该方法,就必须调用基类的实现。该实现预期的接收者是一个对象引用。所以接收者被装箱。
  • 如果接收者已装箱,而且结构重写了该方法,就将箱子的存储位置传给重写的方法,不对其拆箱。
  • 如果接收者已装箱,而且结构没有重写该方法,就将箱子的引用传给基类的实现,该实现预期正是一个引用。

7、枚举

  • 枚举是由开发者声明的值类型。枚举的关键特征是在编译时声明了一组可以通过名称来引用的常量值。例如:
enum ConnectionState
{Disconnected,Connecting,Connected,Disconnecting
}
  • 想要使用枚举值需要为其附加枚举名称前缀。 例如:ConnectionState. Connecting
  • 枚举值实际是作为整数常量实现的,第一个枚举值默认为0, 后续每项都递增1, 然而可以显式为枚举赋值。例如:
enum ConnectionState : short
{Disconnected,Connecting = 10,Connected,Joined = Connected,Disconnecting
}
  • 所有的枚举基类都是System.enum. 后者从System.ValueType 派生。除此之外,不能从现有枚举类型派生以添加额外成员
  • 对于枚举类型,它的值并不限于限于声明中命名的值。 只要值能转换成基础类型,就能转换枚举值。

8、枚举和字符串之间的转换

  • 枚举的一个好处是ToString() 方法会输出枚举值的标识符。
  • 使用Enum.Parse可以将字符串转换为枚举
public static void Main()
{ThreadPriorityLevel priority = (ThreadPriorityLevel)Enum.Parse(typeof(ThreadPriorityLevel), "Idle");Console.WriteLine(priority);
}
  • 为了避免抛出异常,C#4.0 后提供了TryParse 方法。
public static void  Main()
{System.Diagnostics.ThreadPriorityLevel priority;if(Enum.TryParse("Idle", out priority)){Console.WriteLine(priority);}
}

9、枚举作为标志使用

  • 枚举值还可以组合以表示复合值。 此时,枚举声明应使用 Flags 属性进行标记以表示枚举值可以组合,  例如:
[Flags] 
public enum FileAttributes
{None = 0,                             // 000000000000000ReadOnly = 1 << 0,             // 000000000000001Hidden = 1 << 1,                 // 000000000000010System = 1 << 2,                 // 000000000000100Directory = 1 << 4,             // 000000000010000Archive = 1 << 5,                // 000000000100000Device = 1 << 6,                  // 000000001000000Normal = 1 << 7,                // 000000010000000Temporary = 1 << 8,          // 000000100000000SparseFile = 1 << 9,           // 000001000000000ReparsePoint = 1 << 10,   // 000010000000000Compressed = 1 << 11,    // 000100000000000Offline = 1 << 12,              // 001000000000000NotContentIndexed = 1 << 13,    // 010000000000000Encrypted = 1 << 14,        // 100000000000000
}
  • 可以使用按位OR 操作符联结枚举值,使用按位AND操作符测试特定位是否存在
public static void ChapterMain()
{string fileName = @"enumtest.txt";System.IO.FileInfo file = new System.IO.FileInfo(fileName);file.Attributes = FileAttributes.Hidden | FileAttributes.ReadOnly;Console.WriteLine(“{0} | {1} = {2}”,  FileAttributes.Hidden, FileAttributes.ReadOnly,  (int)file.Attributes);if((file.Attributes & FileAttributes.Hidden) != FileAttributes.Hidden)throw new Exception("File is not hidden.");if((file.Attributes & FileAttributes.ReadOnly) != FileAttributes.ReadOnly)throw new Exception("File is not read-only.");
}
  • 枚举声明中也可以用标志组合定义额外的枚举值
[Flags]
enum DistributedChannel
{None = 0,Transacted = 1,Queued = 2,Encrypted = 4,Persisted = 16,FaultTolerant = Transacted | Queued | Persisted
}

良构类型

1、重写ToString

  • 默认情况下,在任何对象上调用ToString() 将返回类的完全限定名称 。例如:在一个Sytem.IO.FileStream对象上调用ToString() 方法将返回字符串 System.IO.FileStream
  • Console.WriteLine() 和System.Diagnostics.Trace.Write 等方法会调用对象的ToString 方法。 因此,重写ToString 输出比默认值更有意义的信息
public struct Coordinate
{public Coordinate(Longitude longitude, Latitude latitude) {Longitude = longitude;Latitude = latitude;}public Longitude Longitude { get; }public Latitude Latitude { get; }public override string ToString() =>$"{ Longitude } { Latitude }";
}
public struct Longitude { }
public struct Latitude { }
  •  由于缺乏本地化和其他高级格式化功能,所以它不太适合一般性用户文本显示

2、重写GetHashCode

        散列码的作用是生成与对象值对应的数字,从而高效地平衡散列表。 为了获得良好的GetHashCode() 的实现,请参照以下原则

  1. 必须:相等的对象必须有相等的散列值。(若a.Equals(b)),则 a.GetHashCode ()== b.GetHashCode()
  2. 必须:在特定对象的生存期内,GetHashCode() 始终返回相同的值,即使对象数据发生了变化。
  3. 必须: GetHashCode() 不应引发任何异常。它总是成功返回一个值
  4. 性能: 散列码应尽可能唯一
  5. 性能: 可能的散列码的值应当尽可能在int 范围内平均分布
  6. 性能: GetHashCode() 的性能应该优化,它通常在Equals 中实现用于“短路”一次完整的相等性比较。所以当类型作为字典集合中的key 使用时,会频繁调用该方法
  7. 性能:两个对象的细微差别应造成散列码的极大差异。 理想情况下,1位的差异应造成散列码平均16位的差异,这有助于保持散列的平衡性
  8. 安全性: 攻击者应该难以伪造具有特定散列值的对象

        在重写Equals或者将类作为散列表集合的键时,需要重写GetHashCode。(如:Collections.HashTable 和 Collections.Generic.Dictionary)

public struct Coordinate
{public Coordinate(Longitude longitude, Latitude latitude){Longitude = longitude;Latitude = latitude;}public Longitude Longitude { get; }public Latitude Latitude { get; }public override int GetHashCode(){int hashCode = Longitude.GetHashCode();// As long as the hash codes are not equalif(Longitude.GetHashCode() != Latitude.GetHashCode()){hashCode ^= Latitude.GetHashCode();  // eXclusive OR}return hashCode;}public override string ToString() => string.Format("{0} {1}", Longitude, Latitude);
}
public struct Longitude { }
public struct Latitude { }

        通常采用的方法是像相关类型的散列码应用XOR 操作符,并确保XOR的操作数不相近或相等。否则结果全为零。在操作数相近或相等的情况下,考虑改为使用移位和加法的操作。

        为了进行更细致的控制,应该使用移位操作符来分解比int 大的类型。 例如,对于一个名为value 的long类型,int GetHashCode() {return ((int)value ^ (int)(value >>32))} ;

        如果基类不是object, 应该在XOR 赋值中包含base.GetHashCode()

        假如计算得到的值可能改变,或者哉将值缓存之后能显著优化性能,就应该对散列值进行缓存。

3、重写Equals

对象同一性 和相等的对象值

  • 两个引用如果引用同一个对象,就说它们是同一的。object 包含名为ReferenceEquals() 的静态方法,它能显式检查对象的同一性
  • 两个对象实例的成员值部分或全部相等,也可以说它们相等      

实现Equals  

  1. 检查是否为null  
  2. 如果是引用类型,就检查引用是否相等
  3. 检查数据类型是否相同
  4. 一个指定了具体类型的辅助方法,它能将操作数视为要比较的类型,而不是将其视为对象
  5. 可能要检查散列码是否相等。  
  6. 如果基类重写了Equals,就检查base.Equals()
  7. 比较每一个标识字段,判断是否相等
  8. 重写GetHashCode
  9. 重写== 和!= 操作符

重写Equals 例子:

//例1:
public sealed class ProductSerialNumber
{public ProductSerialNumber(string productSeries, int model, long id){ProductSeries = productSeries;Model = model;Id = id;}public string ProductSeries { get; }public int Model { get; }public long Id { get; }public override int GetHashCode(){int hashCode = ProductSeries.GetHashCode();hashCode ^= Model;  // Xor (eXclusive OR)hashCode ^= Id.GetHashCode();  // Xor (eXclusive OR)return hashCode;}public override bool Equals(object obj){if(obj == null )return false;if(ReferenceEquals(this, obj))return true;if(this.GetType() != obj.GetType())return false;return Equals((ProductSerialNumber)obj);}        public bool Equals(ProductSerialNumber obj){return ((obj != null) && (ProductSeries == obj.ProductSeries) &&(Model == obj.Model) && (Id == obj.Id));}//....        
}//例2:
public static void Main()
{ProductSerialNumber serialNumber1 =new ProductSerialNumber("PV", 1000, 09187234);ProductSerialNumber serialNumber2 = serialNumber1;ProductSerialNumber serialNumber3 =  new ProductSerialNumber("PV", 1000, 09187234);// These serial numbers ARE the same object identity.if(!ProductSerialNumber.ReferenceEquals(serialNumber1, serialNumber2))throw new Exception("serialNumber1 does NOT " + "reference equal serialNumber2");// And, therefore, they are equal.else if(!serialNumber1.Equals(serialNumber2))throw new Exception("serialNumber1 does NOT equal serialNumber2");else {Console.WriteLine("serialNumber1 reference equals serialNumber2");Console.WriteLine("serialNumber1 equals serialNumber2");}// These serial numbers are NOT the same object identity.if(ProductSerialNumber.ReferenceEquals(serialNumber1, serialNumber3))throw new Exception("serialNumber1 DOES reference " +  "equal serialNumber3");// But they are equal (assuming Equals is overloaded).else if(!serialNumber1.Equals(serialNumber3) ||  serialNumber1 != serialNumber3)throw new Exception("serialNumber1 does NOT equal serialNumber3");Console.WriteLine("serialNumber1 equals serialNumber3");
}

4、比较操作符重载

        实现操作符的过程称为操作符重载. C# 支持重载所有操作符,除了x.y、 f(x)、 new、 typeof、default、checked、unchecked、delegate、is、as、= 和=> 之外    

        一旦重写了Equals, 就可能出现不一致情况,对两个对象执行Equals()可能返回true,但 ==操作符返回false. 因为==默认也是执行引用相等性检查。因此需要重载相等(==)和不相等操作符(!=)  

public sealed class ProductSerialNumber
{//... public static bool operator ==(ProductSerialNumber leftHandSide, ProductSerialNumber rightHandSide){// Check if leftHandSide is null.   (operator== would be recursive)if(ReferenceEquals(leftHandSide, null)){return ReferenceEquals(rightHandSide, null);  // Return true if rightHandSide is also nulland false otherwise.}return (leftHandSide.Equals(rightHandSide));}public static bool operator !=(ProductSerialNumber leftHandSide, ProductSerialNumber rightHandSide){return !(leftHandSide == rightHandSide);}
}

5、二元操作符重载

        +、-、* 、/ 、%、|、^、<<和>> 操作符都被实现为二元静态方法。其中至少一个参数的类型是包容类型。方法名由operator 加操作名构成。 

public struct Arc
{public Arc(Longitude longitudeDifference, Latitude latitudeDifference){LongitudeDifference = longitudeDifference;LatitudeDifference = latitudeDifference;}public Longitude LongitudeDifference { get; }public Latitude LatitudeDifference { get; }
}
public struct Coordinate
{//....public static Coordinate operator +(Coordinate source, Arc arc){Coordinate result = new Coordinate(   new Longitude(  source.Longitude + arc.LongitudeDifference),new Latitude(source.Latitude + arc.LatitudeDifference));return result;}
}

6、 赋值与二元操作符的结合

        只要重载了二元操作符,就自动重载了赋值操作符和二元操作符的结合(+=、-=、/=、%=、&=、|=、^=、<<=和>>=. 所以可以直接使用下列代码     coordinate += arc;  

        它等价于:     coordinate = coordinate + arc;

7、一元操作符

  • 一元操作符的重载类似于二元操作符的重载,只是它们只获取一个参数 该参数必须是包容类型。
public struct Latitude
{//……// UNARYpublic static Latitude operator -(Latitude latitude){return new Latitude(-latitude.Degrees);}public static Latitude operator +(Latitude latitude){return latitude;}
}
  • 重载 true 和 false 时,必须同时重载两个操作符。它们的签名和其他操作符重载必须相同,但是返回值必须时一个bool 值。
public struct Example
{//public static bool operator false(object item)//{//    return true;//    // ...//}//public static bool operator true(object item)//{//    return true;//    // ...//}
}
  • 重载true和false 的操作符类型可以在 if、do、while 和for 语句的控制表达 式中使用

8、引用程序集

        开发者可以将程序的不同部分转移到单独的编译单元中,这些单元称为类库,或者简称库。 然后程序可以引用和依赖类库来提供自己的一部分功能。

更改程序集目标:

        编译器允许通过/target 选项创建下面4种不同的程序集类型  

  1. 控制台程序: 省略target 或者指定 /target:exe  
  2. 类库:/target: library
  3. Window 可执行程序:/target: winexe
  4. 模块:/target : module

引用程序集:    

        C# 允许开发者在命令行上引用程序集。方法是使用 /reference (/r)。

                例如:csc.exe /R:Coordinates.dll Program.cs

9、类型封装

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.xdnf.cn/news/141286.html

如若内容造成侵权/违法违规/事实不符,请联系一条长河网进行投诉反馈,一经查实,立即删除!

相关文章

测试工程师需要具备哪些“技能”?

1、良好的沟通 相信大家都在网上看到过各种吐槽程序员不解风情的段子&#xff0c;开怀大笑之余深思&#xff0c;作为一个测试工程师又何尝不是如此&#xff1f;通常沟通技能成为横亘在测试工程师与其他合作部门之间的万丈鸿沟&#xff0c;也成为测试工程师成长的最大瓶颈。下面…

84、Redis客户端-->可视化图形界面工具(Another Redis Desktop Manager)的下载、安装及初步使用

Redis客户端–>可视化图形界面工具(Another Redis Desktop Manager)的下载、安装及初步使用 ★ Redis客户端&#xff1a; ▲ Redis自带的命令行工具&#xff08;简陋&#xff09;&#xff1a; CLI工具&#xff0c;重新打开一个命令行窗口&#xff0c;在其中输入如下命令&…

Java基础(四)

前言&#xff1a;本博客主要涉及java编程中的线程、多线程、生成者消费者模型、死锁。 目录 线程多线程 线程同步 synchronized Lock锁 线程通信 生产者消费者模型 线程池 使用线程池处理Runnable任务 使用线程池处理Callable任务 Excutors 悲观锁 乐观锁 并发VS并…

迅为iTOP-RK3568开发板Sobel 算子边缘检测

本小节代码在配套资料“iTOP-3568 开发板\03_【iTOP-RK3568 开发板】指南教程 \04_OpenCV 开发配套资料\32”目录下&#xff0c;如下图所示&#xff1a; Sobel (索贝尔)算子是计算机视觉领域的一种重要处理方法。主要用于获得数字图像的一阶梯度,常见的应用和物理意义是边缘检…

3D目标检测实战 | 图解KITTI数据集与数据格式

目录 1 数据集简介2 传感器坐标系3 数据集下载与组织4 数据内容说明4.1 矫正文件calib4.2 图像文件image4.3 点云文件velodyne4.4 标签文件label4.5 平面文件plane 1 数据集简介 KITTI数据集是一个广泛应用于自动驾驶和计算机视觉领域的公开数据集。该数据集由德国卡尔斯鲁厄理…

【Vue】ElementUI实现登录注册

目录 一.跨域的概述 1.1.概述 1.2.特点 二.ElementUI 2.1. 导入 2.2.搭建 2.3.页面 三.数据交互 3.1.安装相关模块 3.1.1安装模块 3.1.2查看模块 3.1.3.引用模块 3.2. axios的get请求 3.3. axios的post请求 四.注册功能 好啦今天到这了&#xff0c;希望能帮到你&…

unity gb28181 rtsp 视频孪生图像拉流和矫正插件(一)

目的是为了视频孪生&#xff0c;将视频放到三维里面&#xff0c;如果使用自己写的插件&#xff0c;有更好的灵活性&#xff0c;同时断线重连等等都更好控制了。 1、矫正算法和硬件解码 最好使用opencv制作&#xff0c;可以使用opencv的cuda加速&#xff0c;opencv的编译&…

Redis 缓存雪崩、缓存穿透、缓存击穿

Redis 是一种常用的内存缓存工具&#xff0c;但在某些情况下&#xff0c;它可能会遭受缓存雪崩、缓存穿透和缓存击穿等问题。下面是一些预防这些问题的建议&#xff1a; 1、缓存雪崩 缓存雪崩指的是在某个时间点上&#xff0c;大量的缓存数据同时失效或过期&#xff0c;导致大…

从管易云到金蝶云星空通过接口配置打通数据

从管易云到金蝶云星空通过接口配置打通数据 数据源平台:管易云 管易云是上海管易云计算软件有限公司旗下的专注提供电商企业管理软件服务的品牌&#xff0c;总部位于中国上海张江高科技产业园区。管易云旗下拥有管易云C-ERP、EC-OMS、EC-WMS、B2C/B2B/BBC/微商城开发、PDA无纸化…

【送书】从不了解用户画像,到用画像数据赋能业务看这一本书就够了丨《用户画像:平台构建与业务实践》

系列文章目录 送书第一期 《用户画像&#xff1a;平台构建与业务实践》 文章目录 系列文章目录前言一、内容简介二、目录三、本书摘要简介总结 前言 在大数据时代&#xff0c;如何有效地挖掘数据价值并通过画像数据进行呈现&#xff0c;如何基于画像数据构建平台功能并提高业…

大数据之Hadoop

大数据 按顺序给出数据存储单位&#xff1a; bit 、 Byte 、 KB、 MB 、 GB 、 TB 、 PB 、 EB 、 ZB 、 YB 、 BB 、 NB 、 DB 。 1Byte 8bit 1K 1024Byte 1MB 1024K 1G 1024M 1T 1024G 1P 1024T Hadoop Hadoop是一个能够对大量数据进行分布式处理的软件框架。 分…

mac怎么把两张图片拼在一起

mac怎么把两张图片拼在一起&#xff1f;在如今的生活中&#xff0c;喜欢摄影的朋友们越来越多。拍照已经成为我们的一种习惯&#xff0c;因为当我们遇到美景或迷人的人物时&#xff0c;总是忍不住按下快门&#xff0c;将它们定格。随着时间的推移&#xff0c;我们渐渐发现自己的…

人工智能安全-2-非平衡数据处理(2)

5 算法层面 代价敏感&#xff1a;设置损失函数的权重&#xff0c;使得少数类判别错误的损失大于多数类判别错误的损失&#xff1b; 单类分类器方法&#xff1a;仅对少数类进行训练&#xff0c;例如运用SVM算法&#xff1b; 集成学习方法&#xff1a;即多个分类器&#xff0c;然…

数据结构--选择排序

目录 选择排序的定义 选择排序的过程 选择排序的算法实现 算法的性能分析 时间、空间复杂度 稳定性 实用性 回顾 选择排序的定义 选择排序的过程 找到最小的元素和第一个元素交换位置 得到 接下来第一个位置不用管了&#xff0c;从剩下的元素中扫描找到最小的元素放到…

[Linux入门]---进程的概念

文章目录 1.进程的概念①描述进程-PCB②task_struct-PCB的一种③task_ struct内容分类 2.查看进程3.通过系统调用获取进程表示符4.通过系统调用创建进程---fork初识 1.进程的概念 在我们的电脑开机的时候&#xff0c;操作系统会被加载到内存中&#xff0c;点击多个应用进行时&a…

【微信小程序开发】宠物预约医疗项目实战-注册实现

【微信小程序开发】宠物预约医疗项目实战-注册实现 第二章 宠物预约医疗项目实战-注册实现 文章目录 【微信小程序开发】宠物预约医疗项目实战-注册实现前言一、打开项目文件二、编写wxss代码2.1 什么是wxss2.2 配置主程序全局样式 三. 在sign文件下的wxml文件中编写如下代码并…

全网最细讲解如何实现导出Excel压缩包文件

写在前面的话 接下来我会使用传统的RESTful风格的方式结合MVC的开发模式给大家介绍一下如何去实现标题的效果。 基本思路讲解 先从数据库中查询出一组人员信息记录&#xff0c;保存在List list中。遍历这个列表&#xff0c;对于每一个人员信息&#xff0c;将其填充到一个Excel…

BIOMOD2模型、MaxEnt模型物种分布模拟,生物多样性生境模拟,论文写作

①基于R语言BIOMOD2模型的物种分布模拟实践技术应用 针对我国目前已有自然保护区普遍存在保护目标不明确、保护成效低下和保护空缺依然存在等问题&#xff0c;科学的鉴定生物多样性热点保护区域与保护空缺显得刻不容缓。 BIOMOD2提供运行多达10余种物种分布模拟模型&#xff0c…

工具篇 | Gradle入门与使用指南

介绍 1.1 什么是Gradle&#xff1f; Gradle是一个开源构建自动化工具&#xff0c;专为大型项目设计。它基于DSL&#xff08;领域特定语言&#xff09;编写&#xff0c;该语言是用Groovy编写的&#xff0c;使得构建脚本更加简洁和强大。Gradle不仅可以构建Java应用程序&#x…

基于海康Ehome/ISUP接入到LiveNVR实现海康摄像头、录像机视频统一汇聚,做到物联网无插件直播回放和控制

LiveNVR支持海康NVR摄像头通EHOME接入ISUP接入LiveNVR分发视频流或是转GB28181 1、海康 ISUP 接入配置2、海康设备接入2.1、海康EHOME接入配置示例2.2、海康ISUP接入配置示例 3、通道配置3.1、直播流接入类型 海康ISUP3.2、海康 ISUP 设备ID3.3、启用保存3.4、接入成功 4、相关…