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

【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、类型封装

相关文章:

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

值类型 1、值类型 值类型的变量直接包含值。换言之&#xff0c; 变量引用的位置就是值内存中实际存储的位置。 2、引用类型 引用类型的变量存储的是对一个对象实例的引用&#xff08;通常为内存地址)。 复制引用类型的值时&#xff0c;复制的只是引用。这个引用非常小&#xf…...

Linux Day18 TCP_UDP协议及相关知识

一、网络基础概念 1.1 网络 网络是由若干结点和连接这些结点的链路组成&#xff0c;网络中的结点可以是计算机&#xff0c;交换机、 路由器等设备。 1.2 互联网 把多个网络连接起来就构成了互联网。目前最大的互联网就是因特网。 网络设备有&#xff1a;交换机、路由器、…...

【Java 基础篇】Java网络编程实时数据流处理

在现代计算机应用程序中&#xff0c;处理实时数据流是一项关键任务。这种数据流可以是来自传感器、网络、文件或其他源头的数据&#xff0c;需要即时处理并做出相应的决策。Java提供了强大的网络编程工具和库&#xff0c;可以用于处理实时数据流。本文将详细介绍如何使用Java进…...

Oracle 和 mysql 增加字段SQL

在Oracle和MySQL中&#xff0c;可以使用ALTER TABLE语句来增加字段。下面是分别是两种数据库增加字段的SQL示例&#xff1a; 在Oracle中增加字段的SQL示例&#xff1a; ALTER TABLE 表名ADD (新字段名 数据类型);例如&#xff0c;如果要在名为"employees"的表中添加…...

【脚本】 【Linux】循环执行命令

loop.sh #!/bin/bashif [ "" "$1" ]; thenecho 用法: ./loop.sh 命令内容 时间间隔(毫秒) 循环次数(小于0表示无限循环)echo 示例: ./loop.sh "ps -ef" 1000 10exit 0 fiinterval1000 if [ "" ! "$2" ]; thenif echo &quo…...

快速用Python进行数据分析技巧详解

概要 一些小提示和小技巧可能是非常有用的&#xff0c;特别是在编程领域。有时候使用一点点黑客技术&#xff0c;既可以节省时间&#xff0c;还可能挽救“生命”。 一个小小的快捷方式或附加组件有时真是天赐之物&#xff0c;并且可以成为真正的生产力助推器。所以&#xff0…...

BD就业复习第二天

Hbase 1. 架构 HBase&#xff08;Hadoop Database&#xff09;是一个开源的分布式、面向列族&#xff08;Column Family&#xff09;的NoSQL数据库&#xff0c;它是构建在Hadoop之上的。HBase的架构设计旨在处理大规模的数据&#xff0c;特别适用于需要快速读写和随机访问大量…...

大数据Flink(八十五):Window TVF 支持多维数据分析

文章目录 Window TVF 支持多维数据分析 一、Grouping Sets 二、​​​​​​​Rollup...

css-边框原理教程

1. CSS中边框原理 他不是一条直线&#xff0c;根据盒子原理&#xff0c;当边框宽度大于元素的长和宽时&#xff0c;呈现一个梯形和三角形的形状&#xff0c;用如下的代码来实地理解一下边框画法实现的原理 注&#xff1a;学习网址&#xff1a; CSS画几种图形的方法_css画图_老…...

【数据结构】时间、空间复杂度

⭐ 作者&#xff1a;小胡_不糊涂 &#x1f331; 作者主页&#xff1a;小胡_不糊涂的个人主页 &#x1f4c0; 收录专栏&#xff1a;浅谈数据结构 &#x1f496; 持续更文&#xff0c;关注博主少走弯路&#xff0c;谢谢大家支持 &#x1f496; 时间、空间复杂度 1. 算法效率3. 时…...

Databend 开源周报第 111 期

Databend 是一款现代云数仓。专为弹性和高效设计&#xff0c;为您的大规模分析需求保驾护航。自由且开源。即刻体验云服务&#xff1a;https://app.databend.cn 。 Whats On In Databend 探索 Databend 本周新进展&#xff0c;遇到更贴近你心意的 Databend 。 理解 SHARE END…...

iOS自动化测试方案(一):MacOS虚拟机保姆级安装Xcode教程

文章目录 一、环境准备二、基础软件三、扩展&#xff1a;usb拓展插件 一、环境准备 1、下载VMware虚拟机的壳子&#xff0c;安装并注册软件(可以百度注册码)&#xff0c;最新版本&#xff1a;v17 2、下MacOS系统iOS镜像文件&#xff0c;用于vmware虚拟机安装&#xff0c;当前镜…...

vue3 - Vue 项目处理GitHub Pages 部署后 _plugin-vue_export-helper.js 404

GitHub Demo 地址 在线预览 vue3项目打包后部署到github pages 后&#xff0c;预览网站提示下划线开头的一个文件_plugin-vue_export-helper访问不到&#xff0c;网络请求显示404 处理GitHub Pages 部署 _plugin-vue_export-helper.js 404 https://github.com/rollup/rollup/b…...

一百八十一、Hive——海豚调度HiveSQL任务时当Hive的计算引擎是mr或spark时脚本的区别(踩坑,附截图)

一、目的 当Hive的计算引擎是spark或mr时&#xff0c;发现海豚调度HQL任务的脚本并不同&#xff0c;mr更简洁 二、Hive的计算引擎是Spark时 &#xff08;一&#xff09;海豚调度脚本 #! /bin/bash source /etc/profile nowdatedate --date0 days ago "%Y%m%d" y…...

Linux 隔离网段下端口转发

设备在隔离网段下&#xff0c;设置端口转发。使A设备可访问C设备的服务 #!/bin/bash #输出成绩脚本 echo -n "请输入外网服务器的IP地址&#xff1a;" read score sudo iptables -t nat -A PREROUTING -p tcp --dport 1883 -j DNAT --to-destination $score:1883 s…...

【CDN和UDN】CDN和UDN技术特点以及使用场景

内容分发网络&#xff08;CDN&#xff09;和用户自定义网络&#xff08;UDN&#xff09;是两种不同的网络技术&#xff0c;在选择时&#xff0c;往往不能准备把握具不同的技术特点和应用场景。CDN 主要用于加速内容分发&#xff0c;而 UDN 则主要用于支持用户自定义的网络需求。…...

【Linux】改变缓存路径、清理缓存

写在前面 在做项目的过程中&#xff0c;服务器base路径下空间不足&#xff0c;准备在另一个目录下创建虚拟环境&#xff0c;但在安装的过程中&#xff0c;发现base路径下的空间还是在减少&#xff0c;后来经过学习了解到&#xff0c;pip安装下载依赖包时&#xff0c;会先下载缓…...

python+opencv寻找图片或视频中颜色进行追踪之HSV颜色处理

pythonopencv寻找图片或视频中颜色进行追踪之HSV颜色处理 1.颜色空间转换 import cv2img cv2.imread(1.jpg) # 转换为灰度图 img_gray cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)cv2.imshow(img, img) cv2.imshow(gray, img_gray) cv2.waitKey(0)cv2.cvtColor()用来进行颜色模…...

ubuntu 22.04 服务器网卡无IP地址

ssh连接服务器连接不上&#xff0c;提示如下&#xff1b; 连接显示器&#xff0c;ip addr ls 命令查看IP地址&#xff0c;有网卡但没有IP地址 solution&#xff1a; sudo dhclient enp10s0用于通过 DHCP 协议获取网络配置信息并为名为 enp10s0 的网络接口分配 IP 地址,enp1…...

基于SpringBoot的网上点餐系统

目录 前言 一、技术栈 二、系统功能介绍 用户功能模块 管理员功能模块 美食店功能模块 前台首页功能模块 三、核心代码 1、登录模块 2、文件上传模块 3、代码封装 前言 系统管理也都将通过计算机进行整体智能化操作&#xff0c;对于网上点餐系统所牵扯的管理及数据保存…...

1688商品列表API与其他数据源的对接思路

将1688商品列表API与其他数据源对接时&#xff0c;需结合业务场景设计数据流转链路&#xff0c;重点关注数据格式兼容性、接口调用频率控制及数据一致性维护。以下是具体对接思路及关键技术点&#xff1a; 一、核心对接场景与目标 商品数据同步 场景&#xff1a;将1688商品信息…...

【C语言练习】080. 使用C语言实现简单的数据库操作

080. 使用C语言实现简单的数据库操作 080. 使用C语言实现简单的数据库操作使用原生APIODBC接口第三方库ORM框架文件模拟1. 安装SQLite2. 示例代码:使用SQLite创建数据库、表和插入数据3. 编译和运行4. 示例运行输出:5. 注意事项6. 总结080. 使用C语言实现简单的数据库操作 在…...

Android 之 kotlin 语言学习笔记三(Kotlin-Java 互操作)

参考官方文档&#xff1a;https://developer.android.google.cn/kotlin/interop?hlzh-cn 一、Java&#xff08;供 Kotlin 使用&#xff09; 1、不得使用硬关键字 不要使用 Kotlin 的任何硬关键字作为方法的名称 或字段。允许使用 Kotlin 的软关键字、修饰符关键字和特殊标识…...

Linux --进程控制

本文从以下五个方面来初步认识进程控制&#xff1a; 目录 进程创建 进程终止 进程等待 进程替换 模拟实现一个微型shell 进程创建 在Linux系统中我们可以在一个进程使用系统调用fork()来创建子进程&#xff0c;创建出来的进程就是子进程&#xff0c;原来的进程为父进程。…...

Unsafe Fileupload篇补充-木马的详细教程与木马分享(中国蚁剑方式)

在之前的皮卡丘靶场第九期Unsafe Fileupload篇中我们学习了木马的原理并且学了一个简单的木马文件 本期内容是为了更好的为大家解释木马&#xff08;服务器方面的&#xff09;的原理&#xff0c;连接&#xff0c;以及各种木马及连接工具的分享 文件木马&#xff1a;https://w…...

纯 Java 项目(非 SpringBoot)集成 Mybatis-Plus 和 Mybatis-Plus-Join

纯 Java 项目&#xff08;非 SpringBoot&#xff09;集成 Mybatis-Plus 和 Mybatis-Plus-Join 1、依赖1.1、依赖版本1.2、pom.xml 2、代码2.1、SqlSession 构造器2.2、MybatisPlus代码生成器2.3、获取 config.yml 配置2.3.1、config.yml2.3.2、项目配置类 2.4、ftl 模板2.4.1、…...

CSS | transition 和 transform的用处和区别

省流总结&#xff1a; transform用于变换/变形&#xff0c;transition是动画控制器 transform 用来对元素进行变形&#xff0c;常见的操作如下&#xff0c;它是立即生效的样式变形属性。 旋转 rotate(角度deg)、平移 translateX(像素px)、缩放 scale(倍数)、倾斜 skewX(角度…...

【Android】Android 开发 ADB 常用指令

查看当前连接的设备 adb devices 连接设备 adb connect 设备IP 断开已连接的设备 adb disconnect 设备IP 安装应用 adb install 安装包的路径 卸载应用 adb uninstall 应用包名 查看已安装的应用包名 adb shell pm list packages 查看已安装的第三方应用包名 adb shell pm list…...

省略号和可变参数模板

本文主要介绍如何展开可变参数的参数包 1.C语言的va_list展开可变参数 #include <iostream> #include <cstdarg>void printNumbers(int count, ...) {// 声明va_list类型的变量va_list args;// 使用va_start将可变参数写入变量argsva_start(args, count);for (in…...

第一篇:Liunx环境下搭建PaddlePaddle 3.0基础环境(Liunx Centos8.5安装Python3.10+pip3.10)

第一篇&#xff1a;Liunx环境下搭建PaddlePaddle 3.0基础环境&#xff08;Liunx Centos8.5安装Python3.10pip3.10&#xff09; 一&#xff1a;前言二&#xff1a;安装编译依赖二&#xff1a;安装Python3.10三&#xff1a;安装PIP3.10四&#xff1a;安装Paddlepaddle基础框架4.1…...