02-C#

坐标转换C#(Gcj02、wgs84、bd09互转) using System; using System.Collections.Generic; using System.Text; namespace GMap.NET.Util { public static class ConvertGPS { private static double pi = 3.1415926535897932384626; private static double... 阅读详情

C#.Net-反射-学习笔记

一、反射基础概念

1.1 什么是反射?

反射(Reflection)是 C# 中的一项强大功能,来自 System.Reflection 命名空间。它允许程序在运行时动态地:

  • 读取程序集(DLL/EXE)的元数据(metadata)
  • 创建对象实例
  • 调用方法
  • 访问字段和属性

1.2 编译过程理解

高级语言(C#代码)
    ↓ 编译
DLL/EXE 文件
    ├── Metadata(元数据):记录了 DLL 中包含的类型、方法等信息
    └── IL(中间语言):编译后的中间代码,面向对象语言

反编译工具(如 ILSpy)也是利用同样的原理,把 dll 逆向还原成 C# 或 IL 代码。

1.3 反射的应用场景

  • 封装框架
  • 系统开发
  • MVC 框架(通过 URL 路由调用方法)
  • IOC 容器(依赖注入)
  • ORM 框架(对象关系映射)

二、反射创建对象

2.1 传统方式 vs 反射方式

传统方式:

IDBHelper dBHelper = new SqlServerHelper();
dBHelper.Query();

缺点:代码与具体类强耦合,切换实现需要修改代码并重新编译。

反射方式(五步走):

// 1. 动态加载 DLL(三种方式)
Assembly assembly = Assembly.LoadFrom("Business.DB.SqlServer.dll");  // DLL 名称
// Assembly assembly = Assembly.LoadFile(@"完整路径\Business.DB.SqlServer.dll");  // 全路径
// Assembly assembly = Assembly.Load("Business.DB.SqlServer");  // 不需要后缀

// 2. 获取类型(需要类的全名称,含命名空间)
Type type = assembly.GetType("Business.DB.SqlServer.SqlServerHelper");

// 3. 创建对象
object oInstance = Activator.CreateInstance(type);

// 4. 类型转换(推荐使用 as,转换失败返回 null 而不是抛异常)
IDBHelper helper = oInstance as IDBHelper;

// 5. 调用方法
helper.Query();

为什么不能直接用 oInstance.Query()?

C# 是强类型语言,编译时以左边声明的类型为准。oInstance 声明为 object,编译器不知道它有 Query 方法,所以编译不通过。

2.2 dynamic 关键字

// 使用 dynamic 可以避开编译器检查,运行时决定类型
dynamic dInstance = Activator.CreateInstance(type);
dInstance.Query();        // 正常
dInstance.NotExist();     // 编译通过,运行时报错

三、简单工厂模式 + 反射 + 配置文件

3.1 实现可配置的工厂

这是反射最核心的应用场景之一,也是 IOC 容器的雏形。

appsettings.json 中配置:

{
  "ReflictionConfig": "Business.DB.Orcale.OrcaleHelper,Business.DB.Orcale.dll"
}

工厂类读取配置,动态创建对象:

public class SimpleFactory
{
    public static IDBHelper CreateInstance()
    {
        string config = CustomConfigManager.GetConfig("ReflictionConfig");
        // 格式:Business.DB.SqlServer.SqlServerHelper,Business.DB.SqlServer.dll
        string typeName = config.Split(',')[0];
        string dllName  = config.Split(',')[1];

        Assembly assembly = Assembly.LoadFrom(dllName);
        Type type = assembly.GetType(typeName);
        object oInstance = Activator.CreateInstance(type);

        return oInstance as IDBHelper;
    }
}

3.2 优势

  • 依赖倒置原则:依赖于抽象(接口)而非具体实现
  • 可配置:切换数据库只需修改配置文件,不需要改代码、不需要重新编译
  • 可扩展:添加新功能只需实现接口、复制 DLL 到执行目录、修改配置文件,无需停止程序

四、反射的"黑科技"——破坏单例

反射可以访问私有构造函数,破坏单例模式:

// 正常单例使用
Singleton singleton1 = Singleton.GetInstance();
Singleton singleton2 = Singleton.GetInstance();
Console.WriteLine(object.ReferenceEquals(singleton1, singleton2));  // True

// 反射破坏单例(第二个参数 true 表示允许访问私有构造函数)
Assembly assembly = Assembly.LoadFrom("Business.DB.SqlServer.dll");
Type type = assembly.GetType("Business.DB.SqlServer.Singleton");
Singleton s1 = (Singleton)Activator.CreateInstance(type, true);
Singleton s2 = (Singleton)Activator.CreateInstance(type, true);
Console.WriteLine(object.ReferenceEquals(s1, s2));  // False - 单例被破坏!

关键点:反射可以无视访问修饰符(private、protected 等)。访问修饰符是编译器层面的约束,反射在运行时直接操作元数据,完全绕过编译器检查。


五、反射调用构造函数和方法

5.1 调用带参数的构造函数

Activator.CreateInstance 的第二个参数接收 object[],按参数类型严格匹配:

Assembly assembly = Assembly.LoadFrom("Business.DB.SqlServer.dll");
Type type = assembly.GetType("Business.DB.SqlServer.ReflectionTest");

// 无参构造
object noParaObject = Activator.CreateInstance(type);

// 有参构造(严格匹配参数类型,没有匹配的构造函数会抛异常)
object paraObject1 = Activator.CreateInstance(type, new object[] { 123 });          // ReflectionTest(int)
object paraObject2 = Activator.CreateInstance(type, new object[] { "张三" });       // ReflectionTest(string)
object paraObject3 = Activator.CreateInstance(type, new object[] { 234, "李四" });  // ReflectionTest(int, string)

5.2 反射调用方法

a. 调用无参方法
object oInstance = Activator.CreateInstance(type);
MethodInfo show1 = type.GetMethod("Show1");
show1.Invoke(oInstance, null);  // 或 new object[0]
b. 调用有参方法(处理重载)

重载方法同名,需要通过参数类型数组来区分:

// Show3(string name, int id)
MethodInfo show31 = type.GetMethod("Show3", new Type[] { typeof(string), typeof(int) });
show31.Invoke(oInstance, new object[] { "张三", 234 });

// Show3(int id)
MethodInfo show32 = type.GetMethod("Show3", new Type[] { typeof(int) });
show32.Invoke(oInstance, new object[] { 345 });
c. 调用私有方法
MethodInfo show4 = type.GetMethod("Show4", BindingFlags.NonPublic | BindingFlags.Instance);
show4.Invoke(oInstance, new object[] { "参数" });
d. 调用静态方法

静态方法调用时,第一个参数(实例)传 null:

MethodInfo show5 = type.GetMethod("Show5");
show5.Invoke(null, new object[] { "参数" });

5.3 调用泛型方法

泛型是"延迟声明",调用时才确定类型。需要先用 MakeGenericMethod 确定类型参数:

Type type = assembly.GetType("Business.DB.SqlServer.GenericMethod");
object oInstance = Activator.CreateInstance(type);

MethodInfo show = type.GetMethod("Show");
// 确定泛型类型参数
MethodInfo genericShow = show.MakeGenericMethod(new Type[] { typeof(int), typeof(string), typeof(DateTime) });
genericShow.Invoke(oInstance, new object[] { 123, "张三", DateTime.Now });

5.4 创建泛型类实例

泛型类的类型名称后面要加反引号和参数数量,如 GenericClass`3,然后用 MakeGenericType 确定类型:

// GenericClass<T, W, X> → "GenericClass`3"
Type type = assembly.GetType("Business.DB.SqlServer.GenericClass`3");
Type genericType = type.MakeGenericType(new Type[] { typeof(int), typeof(string), typeof(DateTime) });
object oInstance = Activator.CreateInstance(genericType);

MethodInfo show = genericType.GetMethod("Show");
show.Invoke(oInstance, new object[] { 123, "张三", DateTime.Now });

5.5 类和方法都有泛型参数

两者需要分别处理,先 MakeGenericType 再 MakeGenericMethod:

// GenericDouble<T> 类 + Show<W, X> 方法
Type type = assembly.GetType("Business.DB.SqlServer.GenericDouble`1");
Type genericType = type.MakeGenericType(new Type[] { typeof(int) });
object oInstance = Activator.CreateInstance(genericType);

MethodInfo show = genericType.GetMethod("Show");
MethodInfo genericMethod = show.MakeGenericMethod(new Type[] { typeof(string), typeof(DateTime) });
genericMethod.Invoke(oInstance, new object[] { 123, "张三", DateTime.Now });

六、反射操作属性和字段

6.1 传统方式

People people = new People();
people.Id = 134;
people.Name = "张三";
people.Age = 25;
Console.WriteLine($"Id={people.Id}, Name={people.Name}");

6.2 反射方式

Type type = typeof(People);
object pObject = Activator.CreateInstance(type);

// 设置属性值
foreach (var prop in type.GetProperties())
{
    if (prop.Name.Equals("Id"))   prop.SetValue(pObject, 134);
    if (prop.Name.Equals("Name")) prop.SetValue(pObject, "张三");
    if (prop.Name.Equals("Age"))  prop.SetValue(pObject, 25);
}

// 获取所有属性值(不需要写死属性名)
foreach (var prop in type.GetProperties())
{
    Console.WriteLine($"people.{prop.Name}={prop.GetValue(pObject)}");
}

// 操作字段
foreach (var field in type.GetFields())
{
    Console.WriteLine($"{field.Name}={field.GetValue(pObject)}");
}

6.3 反射取值的优势

实体类新增属性时,反射代码无需修改,程序更稳定。传统方式则必须修改代码、重新编译发布。


七、手写 ORM 框架(反射 + 泛型)

7.1 核心思想

通过反射 + 泛型实现通用的数据库查询方法,一个方法支持所有实体类型。

7.2 实现代码

public T Find<T>(int id) where T : BaseModel
{
    Type type = typeof(T);
    object oResult = Activator.CreateInstance(type);

    using (SqlConnection connection = new SqlConnection(ConnectionString))
    {
        connection.Open();

        // 反射动态生成 SQL:Select [Id],[Name],... from SysUser where id=1
        string sql = $"Select {string.Join(',', type.GetProperties().Select(c => $"[{c.Name}]"))} from {type.Name} where id={id}";

        SqlDataReader reader = new SqlCommand(sql, connection).ExecuteReader();
        if (reader.Read())
        {
            foreach (var prop in type.GetProperties())
            {
                // DBNull 处理:数据库空值转为 null
                prop.SetValue(oResult, reader[prop.Name] is DBNull ? null : reader[prop.Name]);
            }
        }
    }

    return (T)oResult;
}

7.3 使用示例

SqlServerHelper sqlServer = new SqlServerHelper();
SysCompany company = sqlServer.Find<SysCompany>(1);
SysUser user = sqlServer.Find<SysUser>(17);

前提条件:实体类属性名必须与数据库列名完全一致,且实体类继承 BaseModel(保证有 Id 字段)。

7.4 优化:泛型缓存

每次调用 Find<T> 都重新生成 SQL 是浪费的,同一个类型的 SQL 结构是固定的。利用泛型类的静态构造函数实现缓存:

public class ConstantSqlString<T>
{
    private static string FindSql = null;

    // 静态构造函数:每个泛型类型 T 只执行一次(CLR 保证)
    static ConstantSqlString()
    {
        Type type = typeof(T);
        FindSql = $"Select {string.Join(',', type.GetProperties().Select(c => $"[{c.Name}]"))} from {type.Name} where id=";
    }

    public static string GetFindSql(int id) => $"{FindSql}{id}";
}

使用:

string sql = ConstantSqlString<T>.GetFindSql(id);

原理:ConstantSqlString<SysUser> 和 ConstantSqlString<SysCompany> 是两个不同的类,各自的静态构造函数只执行一次,SQL 模板只生成一次,后续直接复用。


八、反射性能问题

8.1 性能测试结果

实测对比(循环 100 万次创建对象 + 调用方法):

方式耗时
普通 new~17 毫秒
反射(每次 LoadFrom)~6300 毫秒
反射(LoadFrom 缓存到循环外)~71 毫秒

8.2 性能优化建议

把 Assembly.LoadFrom 和 assembly.GetType 提到循环外,只执行一次,后续复用 Type 对象:

// 不推荐:每次都加载
for (int i = 0; i < 1_000_000; i++)
{
    Assembly assembly = Assembly.LoadFrom("Business.DB.SqlServer.dll");
    Type type = assembly.GetType("Business.DB.SqlServer.SqlServerHelper");
    object oInstance = Activator.CreateInstance(type);
}

// 推荐:缓存加载结果
Assembly assembly = Assembly.LoadFrom("Business.DB.SqlServer.dll");
Type dbHelperType = assembly.GetType("Business.DB.SqlServer.SqlServerHelper");
for (int i = 0; i < 1_000_000; i++)
{
    object oInstance = Activator.CreateInstance(dbHelperType);
    IDBHelper helper = (IDBHelper)oInstance;
    helper.Query();
}

结论:反射经过缓存优化后,性能损耗是可以接受的,实际项目中可以放心使用。


九、Emit 技术(动态生成代码)

9.1 什么是 Emit?

Emit 是反射的进阶能力,可以在程序运行时动态生成 dll、类、方法、字段等,来自 System.Reflection.Emit 命名空间。

  • 反射是"读":读取已有程序集的元数据并使用它。
  • Emit 是"写":在运行时动态生成新的程序集和代码。

生成步骤(建造者模式):

AssemblyBuilder → ModuleBuilder → TypeBuilder → FieldBuilder / MethodBuilder

9.2 基本使用

// 1. 创建程序集
AssemblyBuilder assemblyBuilder = AssemblyBuilder.DefineDynamicAssembly(
    new AssemblyName("DynamicAssemblyExample"),
    AssemblyBuilderAccess.RunAndCollect);

// 2. 创建模块
ModuleBuilder moduleBuilder = assemblyBuilder.DefineDynamicModule("MyModal");

// 3. 创建类型
TypeBuilder typeBuilder = moduleBuilder.DefineType("MyDynamicType", TypeAttributes.Public);

// 4. 创建字段
FieldBuilder fieldBuilder = typeBuilder.DefineField("NumberField", typeof(int), FieldAttributes.Public);

// 5. 创建构造函数,用 IL 写逻辑
ConstructorBuilder ctor = typeBuilder.DefineConstructor(
    MethodAttributes.Public, CallingConventions.Standard, new Type[] { typeof(int) });
ILGenerator ctorIL = ctor.GetILGenerator();
ctorIL.Emit(OpCodes.Ldarg_0);  // 加载 this
ctorIL.Emit(OpCodes.Call, typeof(object).GetConstructor(Type.EmptyTypes));
ctorIL.Emit(OpCodes.Ldarg_0);  // 加载 this
ctorIL.Emit(OpCodes.Ldarg_1);  // 加载参数
ctorIL.Emit(OpCodes.Stfld, fieldBuilder);  // 赋值给字段
ctorIL.Emit(OpCodes.Ret);

// 6. 创建方法
MethodBuilder method = typeBuilder.DefineMethod(
    "ConsoleMethod", MethodAttributes.Public | MethodAttributes.Static, null, null);
ILGenerator methodIL = method.GetILGenerator();
methodIL.Emit(OpCodes.Ldstr, "欢迎来到高级班学习");
methodIL.Emit(OpCodes.Call, typeof(Console).GetMethod("WriteLine", new Type[] { typeof(string) }));
methodIL.Emit(OpCodes.Ret);  // IL 方法最后必须有 Ret

// 7. 创建类型并使用
Type dynamicType = typeBuilder.CreateType();
object instance = Activator.CreateInstance(dynamicType, new object[] { 123456 });
MethodInfo consoleMethod = dynamicType.GetMethod("ConsoleMethod");
consoleMethod.Invoke(instance, null);

9.3 特点

  • 动态性强:可在运行时定义业务逻辑
  • 性能极高:生成的代码和手写代码一样快
  • 学习成本高:需要了解 IL 指令
  • 应用场景:动态代理、AOP 切面编程、高性能序列化等

十、反射核心知识点总结

10.1 加载程序集的三种方式

方法参数说明
LoadFromDLL 名称(需要后缀)最常用,支持相对路径,自动解析依赖
LoadFile完整路径(需要后缀)必须绝对路径,不自动解析依赖
LoadDLL 名称(不需要后缀)从 GAC 或应用程序目录加载

10.2 BindingFlags 常用组合

BindingFlags.Public | BindingFlags.Instance    // 公共实例成员
BindingFlags.NonPublic | BindingFlags.Instance  // 私有实例成员
BindingFlags.Public | BindingFlags.Static       // 公共静态成员
BindingFlags.NonPublic | BindingFlags.Static    // 私有静态成员

10.3 typeof(T) vs obj.GetType()

  • typeof(T):编译时操作,T 必须是已知类型名称
  • obj.GetType():运行时操作,返回对象实际运行时类型
IDBHelper helper = new SqlServerHelper();
typeof(IDBHelper)   // → IDBHelper(接口类型)
helper.GetType()    // → SqlServerHelper(实际运行时类型)

10.4 反射的优缺点

优点:

  • 动态性:运行时决定行为
  • 灵活性:解耦具体实现
  • 可扩展性:无需修改代码即可扩展功能
  • 强大性:可访问私有成员

缺点:

  • 性能开销:比直接调用慢(可通过缓存优化)
  • 类型安全:编译时无法检查
  • 代码可读性:相对复杂

十一、实际应用场景

11.1 MVC 框架路由

URL: http://localhost/Home/Index
      ↓
通过反射:
1. 根据 "Home" 创建 HomeController 实例
2. 根据 "Index" 调用 Index 方法

11.2 IOC 容器

// 配置:接口 → 实现类映射
container.Register<IDBHelper, SqlServerHelper>();

// 使用:自动创建实例(底层是反射)
IDBHelper helper = container.Resolve<IDBHelper>();

11.3 ORM 框架

// 一个方法支持所有实体类型
var user = dbContext.Find<SysUser>(1);
var company = dbContext.Find<SysCompany>(1);

附录:常用 API 速查

Assembly 类

Assembly.LoadFrom(string)       // 加载程序集
assembly.GetType(string)        // 获取类型
assembly.GetTypes()             // 获取所有类型
assembly.GetModules()           // 获取所有模块

Type 类

type.GetConstructors()          // 获取构造函数
type.GetMethods()               // 获取方法
type.GetProperties()            // 获取属性
type.GetFields()                // 获取字段
type.GetMethod(name, types)     // 获取指定重载方法
type.MakeGenericType(types)     // 构造泛型类型

Activator 类

Activator.CreateInstance(type)              // 创建实例(无参)
Activator.CreateInstance(type, args)        // 创建实例(有参)
Activator.CreateInstance(type, true)        // 访问私有构造

MethodInfo 类

method.Invoke(instance, parameters)         // 调用方法
method.MakeGenericMethod(types)             // 构造泛型方法

PropertyInfo / FieldInfo 类

prop.GetValue(instance)                     // 获取属性值
prop.SetValue(instance, value)              // 设置属性值
field.GetValue(instance)                    // 获取字段值
field.SetValue(instance, value)             // 设置字段值
C# 精确转换WGS84、GCJ02、BD09坐标系:实现与优化 这些坐标系之间存在一定的偏差和转换关系,特别是在中国境内,WGS84与GCJ02、BD09之间的坐标存在不同程度的偏移。通过理解这些坐标系之间的偏差以及转换算法,我们可以在实际应用中,尤其是在中国境内的地图和定位服务中,准确处理经纬度数据。在实际开发中,根据不同的需求选择适合的坐标转换算法,并对转换精度进行优化,是确保地理定位准确性和可靠性的关键。WGS84到GCJ02的转换存在一定的数学模型,通常是通过一定的偏移量来实现。中进行这些坐标系的相互转换,并且在高精度要求的场景下,提供相关的转换算法。 阅读详情

相关推荐

C#实现 WGS-84与GCJ-02 经纬度坐标转换

C#-WGS-84转GCJ-02 其他语言一样用 //圆周率 private const double pi = 3.14159265358979324; //克拉索天斯基椭球体参数值 private const double a = 6378245.0; //第一偏心率 private const double ee = 0.00669342162296594323; public static GPSPoint WGS84_to_GCJ02(double wgLat, double wgLon) {

weixin_43151814的博客 245

EVA-02在.NET生态中的集成:C#调用与桌面应用开发

本文介绍了如何在星图GPU平台上自动化部署EVA-02: TEXT RECONSTRUCTION TERMINAL镜像,并将其集成到.NET桌面应用中。通过C#调用其API,开发者可以快速为办公软件或内容管理工具添加高效的图片文字提取功能,例如从发票、截图或文档图片中自动重建并获取结构化文本,从而提升工作效率。

weixin_42594427的博客 158

ArcEngine C# GIS开发入门作业 (一) Ex01,Ex02 ——地图、图层加载及属性访问

AE C# GIS 设计与开发课程分享(一) Ex01,Ex02 所以这学期在想学习的动力下,刚结束了GIS开发与设计课,简单入门了刚学的C#和ArcEngine,想趁热写点东西记录下来。 写这篇文章: 1.第一,是为了纪念一下我Domen的入门IT的人生重大转折点; 2.第二是为了锻炼一下自己写作的能力; 3.还有因为我为了增加印象我重新整理了一下自己作业的代码花了很多时间不想浪费,直接拿出...

Domen Wang的博客 7473

C#实战:如何用5行代码搞定WGS84转GCJ02坐标(附避坑指南)

本文详细介绍了在C#开发中实现WGS84到GCJ02坐标系转换的实战方法。针对GPS设备坐标与国内地图服务不匹配的问题,文章提供了核心算法、精简代码示例,并重点分析了浮点数精度、参数传递等常见陷阱,帮助开发者确保定位应用的准确性。

ppp33的博客 695

C# Modbus通信从入门到精通(23)——Modbus TCP(0x02功能码与C#代码实现)

本文详细介绍了ModbusTCP协议中0x02读输入线圈功能码的原理、发送报文、返回报文,由高级工程师多年经验总结而成,绝对干货!

qq_34059233的博客 1654

C# Modbus通信从入门到精通(4)——Modbus RTU(0x02功能码与C#代码实现)

本文详细介绍了ModbusRTU协议中0x02读输入线圈功能码的原理、发送报文、返回报文,由高级工程师多年经验总结而成,绝对干货!

qq_34059233的博客 2927

EVA-02在.NET生态中的集成:C#调用文本重建服务

本文介绍了如何在星图GPU平台上自动化部署🔴 EVA-02: TEXT RECONSTRUCTION TERMINAL镜像,并实现其在.NET生态中的集成。通过C#调用其文本重建服务,开发者可以便捷地为应用(如企业内部知识库智能问答系统)添加智能摘要、内容理解等能力,提升业务系统的智能化水平。

weixin_42611177的博客 178

C# Modbus通信从入门到精通(14)——Modbus ASCII(0x02功能码与C#代码实现)

本文详细介绍了ModbusASCII协议中0x03读输入线圈功能码的原理、发送报文、返回报文,C#代码实现,由高级工程师多年经验总结而成,绝对干货!

qq_34059233的博客 1157

02 认识C#

本文主要介绍了C#的版本,罗列了C#中的一些基础知识。对C#中的数、控制流和类型转换做了些概述。

puran1218的博客 388

C#实现AT24C02 EEPROM小数存储及源码解析

AT24C02是一款常用的串行EEPROM存储器,它使用I²C总线进行通信,广泛应用于需要非易失性存储的电子系统中。该设备提供了2KB的存储空间,可以存储配置数据、用户信息等,且具有较好的抗干扰性和长期数据保持能力。EEPROM(Electrically Erasable Programmable Read-Only Memory)是一种可以随时擦写的非易失性存储器。存储容量是指EEPROM能够存储数据的总量,通常以位(bit)、字节(Byte)或者千字节(KB)、兆字节(MB)为单位进行度量。

weixin_28746213的博客 1032

C++中为什么要引入引用变量?

C++引用机制的设计哲学在于平衡性能与安全性。它解决了指针的三个痛点:语法噪音、空指针风险和语义模糊,同时保持了指针的效率优势。引用必须绑定有效对象且不可重绑定的特性增强了安全性,其值语义语法更直观。尤其在运算符重载和const引用场景中,引用展现了不可替代的优势。本质上,引用是编译器优化的指针实现,体现了C++"零开销抽象"的核心思想——既保持底层性能,又提供高级抽象。这种设计允许开发者根据场景灵活选择指针或引用,反映了C++多范式共存的语言智慧。

教学 & 技术专栏 173

C#—02 变量

常量(Constants)是指在程序中定义的固定不变的值,其值在编译时就确定,并且不能在程序运行时修改。需要注意的是,在进行类型转换时,可能会发生数据丢失或精度损失的情况。因此,在进行类型转换之前,最好确保转换是安全和可靠的,并进行适当的数据验证和处理。字符串型主要用于存储一组连续字符(char),一个完整的字符串对象可以看作是一个 char 类型的数组,既然是数组我们就可以把它当作集合去使用,常量的命名通常使用大写字母,以便与其他变量区分开来,并且常量的值在命名时应该具有描述性,以便于理解其含义。

m0_64778761的博客 1266

光耦选型避坑指南:如何根据CTR参数精准计算输入输出电阻(附24V工业场景实例)

本文深入解析光耦选型核心,聚焦电流传输比(CTR)参数及其衰减特性,提供从输出需求反向推导输入输出电阻的精准计算方法。文章以24V工业场景为例,结合光电耦合器数据手册,详细阐述了如何根据CTR最小值进行降额设计,并给出包含反接保护、TVS管等在内的完整保护电路方案,旨在构建高可靠、长寿命的信号隔离电路,避免因选型或设计不当导致的系统故障。

nept的博客 1038

c#读取dwg零件表_DWGdirect_NET_3_02 找了好久才找到的C#读取DWG格式的CAD文件信息方法,采用OpenDWG的 Windows Develop 249万源代码下载- www....

文件名称: DWGdirect_NET_3_02下载 收藏√ [5 4 3 2 1]开发工具: C#文件大小: 9101 KB上传时间: 2013-10-05下载次数: 124详细说明:找了好久才找到的C#读取DWG格式的CAD文件信息方法,采用OpenDWG的DWGdirect_NET_3_02动态库里的方法,可以完美的读到DWG文件的信息-Looking for a long ...

weixin_39672396的博客 1676

【面试经验】大疆笔试-计算机视觉算法B卷

3、a=np.random.randn(3,3) b=np.random.randn(3,1) ,那么c=a*b的维度应该是:*是元素乘法或者torch.mul,@才是矩阵乘法或者torch.matmul,不会触发广播机制;8、将分辨率降低一半时,精标定内参(fx、fy、cx、cy、k1、k2、k3)焦距、光心、畸变系数将分别变成(fx、fy、cx/2、cy/2、k1、k2、k3),只能搜到光心变成一半,畸变系数不变。12、KLT算法在频闪光源、重复纹理、高速机动、环境照度低的情况下效果显著下降。

litterfinger的博客 1444

ANSYS Maxwell:创建即用型 3D 轴向磁通电机模型

Magnet Length” 是磁体的径向长度。“Magnet Thickness” 是磁体的轴向长度。为了对 AFM 进行更详细的分析,用户需要在 ANSYS Maxwell 中运行 3D FEA 分析。对于 2D 模型,它们类似于 MotorCAD 中的模型,后者对等效的直线电机进行建模。单击“确定”后,将创建一个 3D Maxwell 模型。“长度”是转子铁的轴向长度。然后需要定义定子的“磁芯”尺寸和材料。“长度”是定子铁芯的轴向长度。“转子”# 的极数必须与“定子”中定义的磁极相同。

jkh920184196的博客 1930

C#02

01:在C#中,string str = null 与 string str = “” 请尽量使用文字或图 象说明其中的区别。 string str = null 没有创建内存空间,str中存放的是空引用指针; string str = "" 创建了内存空间,str中存放的是指向堆中的指针。 简单地说: string str =""; 给你一张白纸; string str = null; ...

Jdouble的博客 140

RAGFlow源码解析-2、从源码构架ragflow v0.25.0镜像

本文详细记录了从零开始构建自定义RAGFlow镜像lt/ragflow:0.25.0的全过程。首先介绍了环境准备,包括检查Node.js、Docker版本和项目结构。然后详细说明了构建步骤:编译前端、创建自定义Dockerfile、构建镜像和验证。接着讲解了docker-compose配置修改要点,包括网络定义、MySQL依赖处理等。最后总结了部署过程中遇到的五个关键问题及解决方案,包括networks未定义、MySQL服务依赖、tiktoken文件缺失、数据库配置错误和端口映射问题。通过完整的操作流程和问

liutao841204的专栏 364

C#基础02

01:在C#中,string str = null 与 string str = “” 请尽量使用文字或图说明其中的区别 string str=null 把这个引用指向了一个null,没有地址没有值的地方。 string str="" 把这个引用指向了一个地址,地址里面存的是空的字符。 string str=""就相当于一个人考试了,不过是考了0分; 而 string str=null 就...

qq_43227356的博客 166

LeRobot — 基于 PyTorch 的真实世界机器人学习框架(一)- 核心框架模块解析

LeRobot 是一个开源的机器人学习框架,由 Hugging Face 开发,旨在降低机器人学的准入门槛。该框架提供完整的机器学习流程支持,包括数据采集、训练、评估和部署。核心模块涵盖数据集标准化、策略算法、硬件抽象和强化学习组件,采用模块化设计实现灵活扩展。通过集成 Hugging Face Hub,用户可以轻松共享数据集和预训练模型。LeRobot 特别注重真实世界的机器人应用,支持多种前沿算法如模仿学习、视觉语言动作模型等,并提供统一的硬件接口和仿真环境适配。

熊猫小妖的AI世界 170

STM32串口编程基础知识讲解

本篇文章给大家介绍一下串口的基础编程知识,这些知识是属于串口的理论知识,在开始学习编写代码的时候必须要掌握这些基本的知识点。本篇文章讲解了串口的基本概念知识,大家在学习编写代码时将其掌握才能更好的理解代码。

m0_49476241的博客 1207

EVA-02模型.NET平台调用实战:C#集成开源大模型文本服务

本文介绍了如何在星图GPU平台上自动化部署🔴 EVA-02: TEXT RECONSTRUCTION TERMINAL镜像,以快速搭建大模型服务环境。通过该平台,开发者可便捷地获取并运行此镜像,从而在C#/.NET项目中集成EVA-02模型的文本生成能力,实现智能对话、代码生成等应用场景。

weixin_35749440的博客 203

撸毛笔记-朴朴超市 v1.01

朴朴超市 v1.01脚本地址:自动签到和组队赚朴分, 朴分可以抵扣50%的金额组队瓜分需要4人成团, 每个号每天只能开团和入队各一次每天跑一两次即可使用扫码或自己想办法捉refreshToken扫码获取token: (先微信进入朴朴超市小程序并登录注册过账号再扫码)把获取的refreshToken和备注(非必须)填到文件pupuCookie.txt里(第一次运行会自动创建), 多账号换行或&或@隔开。

xiaoshun007的专栏 1804

C#基础— 02

一、基本用法 1、Console.ReadLine();等待用户输入一行字符串后按下回车,一次读入一行。 2、Console.ReadKey();等待用户输入一个字符(任意键),一次读入一个字符。常加在程序的结尾处,方便调试的时候,控制台窗口能暂停等待用户输入,而不会一闪而过。 3、C#条件表达式为 条件表达式 ? 分支1 : 分支2 。条件表达式为真时,输出分支1的结果;条件表达式...

Jeffxu_lib的博客 2024

IDEA的使用指南

IDEA基于java的使用手册,可以最快速的上手,在使用中不断的丰富自己的使用技巧.

jre9下载 jdk9

(Java SE Runtime Environment 9.0) 9.0u175 官方最新版 【x86|x64】

C#笔记02 C#的基本语法

C#笔记02 C#的基本语法 C#是可用于创建要运行在.NET CLR上的应用程序的语言之一,它从C和C++语言演化而来,是Microsoft专门为使用.NET平台而创建的。使用C#开发应用程序比使用C++简单,因为其语法比较简单。但是,C#是一种强大的语言,在C++中能完成的任务几乎都能利用C#完成。——清华大学出版社《C#入门经典(第五版)》 写在前边: C#程序由一个或多个类型声明组成,可以以任何顺序声明。 1. 标识符和关键字 1.1 标识符用来命名变量 、方法、参数和许多其他程序结构之类的东西

Tervor_HAN的博客 281

Devexpress16.2.6破解工具

Devexpress16.2.6破解工具Devexpress16.2.6破解工具Devexpress16.2.6破解工具Devexpress16.2.6破解工具

上一篇: 14-C#
下一篇: 04-C#
似水明俊德
博客等级 码龄8年 247粉丝 276原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值