C# 12主构造函数完全教程:3步实现代码极简主义

工业场景实战:基于YOLO与多格式标注的传送带异物检测数据集构建指南 本文详细介绍了基于YOLO与多格式标注的传送带异物检测数据集构建方法,涵盖数据采集、标注技巧(YOLO、COCO、VOC格式)、数据增强策略及实战案例。通过工业级解决方案,有效提升异物检测准确率与效率,适用于各类工业场景。 阅读详情

第一章:C# 12 主构造函数 简化编程

C# 12 引入了主构造函数(Primary Constructors)这一重要特性,显著简化了类和结构体中构造逻辑的编写方式。通过主构造函数,开发者可以在类声明的同一行中定义参数,并自动将其用于初始化内部成员,从而减少样板代码。

主构造函数的基本语法

在 C# 12 中,类或结构体可以直接在类型名称后接收参数,这些参数可用于整个类型的上下文中:
// 使用主构造函数定义 Person 类
public class Person(string name, int age)
{
    public string Name { get; } = name;
    public int Age { get; } = age;

    public void Introduce()
    {
        Console.WriteLine($"Hello, I'm {Name} and I'm {Age} years old.");
    }
}

// 使用示例
var person = new Person("Alice", 30);
person.Introduce();
上述代码中,string name 和 int age 是主构造函数的参数,可在属性初始化时直接使用,无需显式声明私有字段或在构造函数体内赋值。

适用场景与优势

  • 减少冗余代码:避免重复书写构造函数和字段赋值逻辑
  • 提升可读性:构造参数一目了然,类型意图更清晰
  • 适用于记录和 DTO 类型:尤其适合数据承载类的简洁定义

与传统构造函数对比

特性主构造函数传统构造函数
代码量少多
可读性高中
适用类型简单数据类、记录复杂初始化逻辑
主构造函数并非取代所有构造函数场景,而是为简化常见模式提供更优雅的语法选择。对于需要复杂验证或多个重载构造函数的情况,仍可结合使用常规实例构造函数。

第二章:主构造函数的核心语法与原理

2.1 主构造函数的语法结构解析

在现代编程语言中,主构造函数是类初始化的核心机制。它通常位于类定义的首部,直接接收参数并自动完成字段赋值。
基本语法形式
以 Kotlin 为例,主构造函数通过 constructor 关键字声明,可包含带默认值或不带默认值的参数:
class User(val name: String, val age: Int = 18) {
    init {
        println("创建用户:$name,年龄:$age")
    }
}
上述代码中,val 声明使参数直接成为类的只读属性,init 块用于执行初始化逻辑。
参数修饰与可见性
主构造函数支持多种修饰符控制访问级别:
  • public:公共可访问(默认)
  • private:仅类内部可用
  • protected:子类可继承

2.2 与传统构造函数的对比分析

在现代JavaScript中,类(class)的引入为对象创建提供了更清晰的语法结构,而传统构造函数则依赖于原型链机制。
语法简洁性
ES6类语法更加直观,提升了可读性。例如:

class Person {
  constructor(name) {
    this.name = name;
  }
  greet() {
    console.log(`Hello, I'm ${this.name}`);
  }
}
上述代码等价于传统构造函数写法:

function Person(name) {
  this.name = name;
}
Person.prototype.greet = function() {
  console.log(`Hello, I'm ${this.name}`);
};
类的写法将构造逻辑和方法定义集中在一起,结构更紧凑。
继承实现对比
  • 类继承使用 extends 关键字,语法清晰;
  • 传统方式需手动操作原型链,易出错且难以维护。
特性类(Class)构造函数
语法复杂度低高
继承支持原生支持需手动实现

2.3 参数传递与字段初始化机制

在Go语言中,参数传递遵循值传递原则,无论是基本类型还是复合类型,实参的副本被传递给函数。对于指针或引用类型(如slice、map),副本仍指向同一底层数据,因此可实现类似“引用传递”的效果。
值传递与指针传递对比
func modifyValue(x int)   { x = 100 }
func modifyPointer(x *int) { *x = 100 }

val := 10
modifyValue(val)  // val 仍为 10
modifyPointer(&val) // val 变为 100
modifyValue 接收的是 val 的副本,原值不受影响;而 modifyPointer 接收地址,可修改原始内存。
结构体字段初始化
使用字面量初始化时,字段按声明顺序赋值,未显式指定的字段将赋予零值。
字段初始化值
Name"Alice"
Age0(默认)

2.4 主构造函数的作用域与生命周期

主构造函数在类初始化时执行,其作用域限定于实例创建阶段,负责参数注入与字段初始化。
执行时机与可见性
主构造函数的参数默认为类成员,可在整个类体中访问,但无法在静态上下文中引用。
class User(val name: String, val age: Int) {
    init {
        println("Initializing user: $name")
    }
}
上述代码中,name 与 age 被自动提升为属性,init 块在构造期间执行。参数作用域覆盖整个实例生命周期。
生命周期管理
对象销毁由垃圾回收器控制,主构造函数不参与清理工作。资源释放应依赖显式接口或析构函数。
  • 构造函数仅运行一次,确保状态一致性
  • 参数值在对象存活期间可被访问
  • 不可重新调用主构造函数重置状态

2.5 编译器如何处理主构造函数

在现代编程语言如 Kotlin 和 C# 中,主构造函数被作为类声明的一部分直接定义。编译器会解析主构造函数的参数并自动生成相应的字段与初始化逻辑。
参数处理与字段生成
主构造函数中的参数若带有修饰符(如 val 或 var),编译器将自动提升为类的属性,并在生成的字节码中创建对应的字段和访问器。
class Person(val name: String, age: Int)
上述代码中,name 被声明为公开属性,编译器生成私有字段与 getter;而 age 仅作为构造参数使用,不会生成字段,除非在类体内显式引用。
字节码生成流程
  • 解析主构造函数签名
  • 绑定参数到类属性或局部变量
  • 生成默认构造方法并插入初始化语句
编译器最终输出的字节码等效于显式编写构造函数的行为,但大幅简化了源码结构。

第三章:简化对象初始化的实践技巧

3.1 在记录类型中应用主构造函数

在C# 9及更高版本中,记录(record)类型引入了主构造函数的简洁语法,允许将参数直接内联在类型定义中,从而简化不可变类型的创建。
主构造函数语法结构
使用主构造函数时,参数被声明在类型名称后的括号中,并可用于初始化属性:
public record Person(string FirstName, string LastName);
上述代码定义了一个 Person 记录类型,其主构造函数接受两个参数。编译器自动生成只读属性、Deconstruct 方法以及基于值的相等性比较逻辑。
参数说明与行为特征
  • FirstName 和 LastName 被自动提升为公共只读属性;
  • 实例化时无需显式定义构造函数体:var person = new Person("John", "Doe");;
  • 支持位置解构:var (first, last) = person;。
该机制显著减少了样板代码,提升了领域模型建模的表达力与安全性。

3.2 结合属性初始化器实现简洁代码

在现代编程语言中,属性初始化器允许在声明字段时直接赋予初始值,从而减少构造函数中的模板代码。
简化对象初始化
使用属性初始化器,无需在构造函数中重复赋值,提升代码可读性。例如在 C# 中:

public class User
{
    public string Name { get; set; } = "Unknown";
    public int Age { get; set; } = 18;
    public List Hobbies { get; set; } = new List();
}
上述代码中,Name、Age 和 Hobbies 在声明时即完成初始化,避免了每个构造函数中重复实例化。
优势对比
  • 减少构造函数冗余代码
  • 确保集合类字段不为 null
  • 支持多构造函数场景下的统一初始化逻辑
该特性尤其适用于配置类、DTO 等数据承载类型,显著提升开发效率与代码整洁度。

3.3 避免重复代码:构造参数的智能复用

在构建复杂系统时,频繁重复传递相同参数不仅冗余,还容易引发维护问题。通过智能复用构造参数,可显著提升代码可读性与可维护性。
使用配置对象统一参数
将多个构造参数封装为配置对象,避免函数签名膨胀:
type ServerConfig struct {
    Host string
    Port int
    TLS  bool
}

func NewServer(config ServerConfig) *Server {
    // 使用 config 初始化服务
}
该方式将分散参数归一管理,后续扩展无需修改函数定义。
依赖注入促进复用
通过依赖注入框架自动解析并传递构造参数,减少手动组装:
  • 降低组件间耦合度
  • 提升测试便利性
  • 支持运行时动态替换实现
参数不再是散落在各处的魔法值,而是集中、可配置的实体。

第四章:真实项目中的高级应用场景

4.1 在依赖注入中简化服务类构造

依赖注入(DI)通过外部容器管理对象依赖关系,显著降低了服务类的耦合度与构造复杂性。
构造函数注入示例
type UserService struct {
    repo UserRepository
}

func NewUserService(r UserRepository) *UserService {
    return &UserService{repo: r}
}
上述代码使用构造函数注入,将 UserRepository 实例由外部传入,避免在结构体内直接初始化,提升可测试性与灵活性。
依赖注入的优势
  • 解耦业务逻辑与依赖创建
  • 便于单元测试中使用模拟对象(Mock)
  • 支持灵活配置不同环境下的实现
通过 DI 容器统一管理生命周期,服务类无需关注依赖的实例化过程,专注核心逻辑实现。

4.2 与Entity Framework Core结合使用

在现代.NET应用开发中,将缓存机制与ORM框架协同工作是提升性能的关键策略。Entity Framework Core(EF Core)作为主流数据访问技术,可与内存缓存无缝集成,减少数据库往返次数。
查询结果缓存
通过拦截EF Core的查询执行流程,可将频繁读取的结果缓存到内存中。例如:
// 使用IMemoryCache缓存EF Core查询结果
var products = await _cache.GetOrCreateAsync("products", async entry =>
{
    entry.SlidingExpiration = TimeSpan.FromMinutes(10);
    return await _context.Products.ToListAsync();
});
上述代码利用GetOrCreateAsync方法实现缓存获取或异步填充,SlidingExpiration设置滑动过期策略,有效降低数据库负载。
数据同步机制
当底层数据变更时,需及时清除对应缓存项。可通过重写SaveChangesAsync方法,在实体保存后触发缓存清理:
  • 监测被修改的实体类型(如Product)
  • 移除相关缓存键(如"products")
  • 确保下次读取获取最新数据

4.3 构建不可变对象的最佳实践

在面向对象编程中,不可变对象一旦创建其状态便不可更改,这极大提升了线程安全性和代码可预测性。
使用私有字段与终态修饰符
通过将字段声明为 private final,确保对象状态无法被外部修改,且在构造时完成初始化。
public final class Person {
    private final String name;
    private final int age;

    public Person(String name, int age) {
        this.name = name;
        this.age = age;
    }

    public String getName() { return name; }
    public int getAge() { return age; }
}
上述代码中,final 保证了引用不可变,配合私有访问控制实现完全封装。构造函数是唯一状态注入途径,避免运行时状态污染。
防御性拷贝
当字段包含可变对象(如集合或日期)时,需在构造和访问时进行深拷贝。
  • 构造函数中对传入的可变对象执行拷贝
  • Getter 方法返回对象副本而非原始引用
  • 防止外部绕过不可变机制直接修改内部状态

4.4 处理复杂构造逻辑的折中方案

在面对对象初始化逻辑日益复杂的场景时,直接使用构造函数易导致参数膨胀与职责混乱。一种有效的折中是引入**构建者模式**(Builder Pattern),将构造过程分解为多个可链式调用的步骤。
链式配置示例

type Server struct {
    host string
    port int
    tls  bool
}

type ServerBuilder struct {
    server *Server
}

func NewServerBuilder() *ServerBuilder {
    return &ServerBuilder{server: &Server{}}
}

func (b *ServerBuilder) Host(host string) *ServerBuilder {
    b.server.host = host
    return b
}

func (b *ServerBuilder) Port(port int) *ServerBuilder {
    b.server.port = port
    return b
}

func (b *ServerBuilder) EnableTLS() *ServerBuilder {
    b.server.tls = true
    return b
}

func (b *ServerBuilder) Build() *Server {
    return b.server
}
上述代码通过 ServerBuilder 将构造逻辑解耦,每步返回自身实现链式调用,最终由 Build() 完成实例化。该方式提升了可读性与扩展性,同时避免了构造函数参数列表过长的问题。

第五章:总结与展望

技术演进的实际路径
现代后端架构正从单体向服务网格快速迁移。以某电商平台为例,其订单系统在QPS超过5万时出现延迟激增,通过引入gRPC替代REST,并启用双向流式通信,整体响应时间下降62%。

// 启用gRPC流式处理订单状态更新
func (s *OrderService) StreamStatus(req *StreamRequest, stream pb.OrderService_StreamStatusServer) error {
    for _, order := range s.getOrders(req.UserId) {
        if err := stream.Send(&pb.StatusUpdate{OrderId: order.Id, Status: order.Status}); err != nil {
            return err
        }
        time.Sleep(100 * time.Millisecond) // 模拟实时推送
    }
    return nil
}
可观测性的落地实践
在微服务环境中,分布式追踪成为排查性能瓶颈的关键。以下为OpenTelemetry在Go服务中的基础配置方案:
  • 集成OTLP协议上报追踪数据
  • 使用Jaeger作为后端分析引擎
  • 关键路径注入Span上下文
  • 设置采样率避免日志风暴
指标类型采集工具告警阈值
请求延迟(P99)Prometheus + Grafana>800ms
错误率ELK + OpenTelemetry>1%
服务调用拓扑图示例:
API Gateway → Auth Service → Order Service ⇄ Inventory Service
                       ↓
                    Logging & Tracing Backend
Hierarchical Flow Partition(Top-down&&Bottom-up) hierarchy flow是将设计切分成多个block,分别处理单个block,然后完成后,将它们进行拼接以完成最终的chip。一般划分为三个阶段:chip planning;physical budget就是pin assignmenthierarchy flow实现的方法有两种,一种是top-down,另一种是bottom-up,无论是哪种,都是都要通过flatten的方法分别全局范围进行优化实现。 阅读详情

相关推荐

七步设计高频变压器

七步设计高频变压器

m0_71394959的博客 5401

C# 12主构造函数完全指南:从入门到精通必须掌握的3种高级用法

掌握C# 12主构造函数高效编程方法,解决传统构造冗余问题。涵盖记录类型、依赖注入与不可变对象场景,结合C# 12主构造函数示例讲解核心用法与性能优势,代码更简洁安全,值得收藏。

StepLens的博客 578

OB4.X集群状态running但是oceanbase-ce is not running

自 V3.2.0 起,若 obd 设置了加密密钥,执行 display 命令输出的集群信息中,密码相关内容为加密状态。若需输出明文密码,可在命令中添加 --epk/–encryption-passkey 指定密钥用于验证。obd 运维的数据库,启停需要使用obd进行操作,停机时候没有使用obd会导致集群状态running但是oceanbase-ce is not running。查看集群中的租户时无租户反馈,警告oceanbase-ce is not running,但是查询集群状态明明是running。

qq961573863的博客 1213

C# 12主构造函数到底怎么用?3个实战案例教你高效编程

掌握C# 12主构造函数的高效用法,解决代码冗余问题。通过3个实战案例详解在计算属性、依赖注入和数据模型中的应用,提升开发效率与代码可读性。C# 12主构造函数计算技巧一文掌握,值得收藏。

PoliVein的博客 721

MATLAB控制信号发生器(USB-GPIB-HS)GPIB仪器控制教程(含matlab代码)

自动化测试时需要自动产生信号,通过matlab控制信号发生器的频率与功率,以实现自动化信号生成输出

qq_43686057的博客 1606

SDA 还是 SDI:SAP HANA 数据虚拟化与数据集成的取舍、组合与实战

结论先放在前面:SDA 面向数据虚拟化与联邦查询,强调不落地、不复制、按需实时访问;SDI 面向数据集成与复制,强调抽取、转换、装载与近实时增量同步。两者共享 Remote Source 与 Adapter 的理念,但侧重点与运行时组件明显不同。

2007 年 ~ 2025 年,深耕 SAP 技术 18 年 585

【C# 12开发效率飞跃指南】:主构造函数如何重构你的代码结构?

提升代码简洁性与可维护性,C# 12主构造函数简化类型声明,适用于计算模型等场景。通过一行代码整合参数与字段,减少样板代码,提升开发效率。C# 12主构造函数计算更优雅,值得收藏。

InstrFun的博客 980

逆向分析顶象5代各类验证码类型的图片还原方法(附源码)

6.刷新滑块验证码图片,会进入之前的for循环断点,分析此处的代码会发现,该循环循环了处理了n字符串的值,取出n字符中的值并使用charCodeAt生成Unicode 编码,然后又调用了a函数,如果a函数返回true就会把之前生成的Unicode编码+1,a函数参数分别是c数组和Unicode取余32后的值,然后再把Unicode取余32后的值push进c数组,这里的n值为滑块碎片背景图的name。2.搜索"ranges":,会找到ranges赋值的地方,在此处代码断点,并点击跳过断点,结束此次调试。

老衲爱洗头的博客 1196

深入理解 C# 中的主构造函数

深入理解 C# 中的主构造函数

鲤籽鲲的博客 1652

Open3D 三维重建-Delaunay Triangulation (德劳内三角剖分)

德劳内三角剖分(Delaunay Triangulation)是一种用于从一组点生成三角形网格的算法。它的特点是使得生成的三角形尽量接近等边三角形,即最大化最小角度,避免生成细长的三角形。

纵马踏花向自由 2502

华为OD机试2025A卷 - 用户调度问题(Java & Python& JS & C++ & C )

题目要求每个用户依次选择当前所能选择的最小资源消耗策略,并且若有多个策略的资源消耗相同,则选择最后一个策略。每个用户的选择是独立的,只考虑该用户的策略和相邻用户的约束,不考虑整个调度序列的全局资源消耗。每个用户根据自己的当前状态(即自己的三种选择的资源消耗)做出局部最优选择:在当前可选的策略中,选择消耗最小的那个。如果有多个最小值,则选择最后一个(根据题意)。这一选择是局部的最优,即在当下最有利的选择,但并不保证最终的整体系统资源消耗是最小的。

算法大师! 1万+

C# 12主构造函数陷阱频发?专家教你3步搞定基类参数传递难题

掌握C# 12主构造函数基类调用的正确方式,3步解决参数传递难题。适用于继承场景,通过构造委托、参数显式传递与基类型声明优化代码结构,提升可读性与维护性,避免常见编译错误,值得收藏。

FuncLens的博客 1041

AD18软件——捕捉栅格、电气栅格、可见栅格的意义及设置

本文介绍了PCB设计中的三种栅格功能:可视栅格用于辅助定位(快捷键Shift+Ctrl+G),捕捉栅格控制光标移动间距(快捷键G),电气栅格实现元件自动吸附(快捷键Shift+E)。同时提供了在Altium Designer中快速查找相同网络标号的两种实用方法:Alt+鼠标单击或双击网络。这些功能可显著提高PCB设计效率和准确性。

qq_37999850的博客 646

C# 12主构造函数新特性全面解读(主构造函数计算黑科技)

掌握C# 12主构造函数计算技巧,提升代码简洁性与性能。本文详解主构造函数在对象初始化中的实际应用、计算属性的高效用法及简化语法的优势,适用于实体类与DTO场景,大幅减少样板代码,值得收藏。

FastCompile的博客 797

IEM模型,地表粗糙度模拟

利用微波反演土壤水分时候,利用IEM模型可以实现对随机地表的模拟

霍尼韦尔SoftMaster使用说明

霍尼韦尔SoftMaster使用说明

C# 12主构造函数全面指南,一文掌握7种高效计算模式

掌握C# 12主构造函数计算新特性,提升代码简洁性与性能。本文详解7种高效计算模式的适用场景与实现方法,涵盖类、记录、结构体中的实际应用,助你快速构建现代化C#程序。模式实用,语法清晰,值得收藏。

Algorhythm的博客 751

复分析 阿尔福斯(Ahlfors) 第三版答案 英文

答案分为十章,有部分习题没有答案,全英文复分析阿尔福斯(Ahlfors) 第三版答案

【C# 12主构造函数深度解析】:掌握简化编程的终极利器

掌握C# 12主构造函数,轻松实现代码简化编程。适用于记录类型、依赖注入等场景,减少样板代码,提升开发效率。一行代码定义并初始化字段,简洁又高效。值得收藏

GatherLume的博客 722

深度学习工具包 DeepLearningToolbox

深度学习工具包Deprecation notice.-----This toolbox is outdated and no longer maintained.There are much better tools available for deep learning than this toolbox, e.g. [Theano](http://deeplearning.net/software/theano/), [torch](http://torch.ch/) or [tensorflow](http://www.tensorflow.org/)I would suggest you use one of the tools mentioned above rather than use this toolbox.Best, Rasmus.DeepLearnToolbox================A Matlab toolbox for Deep Learning.Deep Learning is a new subfield of machine learning that focuses on learning deep hierarchical models of data.It is inspired by the human brain&#39;s apparent deep (layered, hierarchical) architecture.A good overview of the theory of Deep Learning theory is[Learning Deep Architectures for AI](http://www.iro.umontreal.ca/~bengioy/papers/ftml_book.pdf)For a more informal introduction, see the following videos by Geoffrey Hinton and Andrew Ng.* [The Next Generation of Neural Networks](http://www.youtube.com/watch?v=AyzOUbkUf3M) (Hinton, 2007)* [Recent Developments in Deep Learning](http://www.youtube.com/watch?v=VdIURAu1-aU) (Hinton, 2010)* [Unsupervised Feature Learning and Deep Learning](http://www.youtube.com/watch?v=ZmNOAtZIgIk) (Ng, 2011)If you use this toolbox in your research please cite [Prediction as a candidate for learning deep hierarchical models of data](http://www2.imm.dtu.dk/pubdb/views/publication_details.php?id=6284)```@MASTERSTHESIS\{IMM2012-06284, author = "R. B. Palm", title = "Prediction as a candidate for learning deep hierarchical models of data", year = "2012",}```Contact: rasmusbergpalm at gmail dot comDirectories included in the toolbox-----------------------------------`NN/` - A library for Feedforward Backpropagation Neural Networks`CNN/` - A library for Convolutional Neural Networks`DBN/` - A library for Deep Belief Networks`SAE/` - A library for Stacked Auto-Encoders`CAE/` - A library for Convolutional Auto-Encoders`util/` - Utility functions used by the libraries`data/` - Data used by the examples`tests/` - unit tests to verify toolbox is workingFor references on each library check REFS.mdSetup-----1. Download.2. addpath(genpath(&#39;DeepLearnToolbox&#39;));Example: Deep Belief Network---------------------```matlabfunction test_example_DBNload mnist_uint8;train_x = double(train_x) / 255;test_x = double(test_x) / 255;train_y = double(train_y);test_y = double(test_y);%% ex1 train a 100 hidden unit RBM and visualize its weightsrand(&#39;state&#39;,0)dbn.sizes = [100];opts.numepochs = 1;opts.batchsize = 100;opts.momentum = 0;opts.alpha = 1;dbn = dbnsetup(dbn, train_x, opts);dbn = dbntrain(dbn, train_x, opts);figure; visualize(dbn.rbm{1}.W&#39;); % Visualize the RBM weights%% ex2 train a 100-100 hidden unit DBN and use its weights to initialize a NNrand(&#39;state&#39;,0)%train dbndbn.sizes = [100 100];opts.numepochs = 1;opts.batchsize = 100;opts.momentum = 0;opts.alpha = 1;dbn = dbnsetup(dbn, train_x, opts);dbn = dbntrain(dbn, train_x, opts);%unfold dbn to nnnn = dbnunfoldtonn(dbn, 10);nn.activation_function = &#39;sigm&#39;;%train nnopts.numepochs = 1;opts.batchsize = 100;nn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.10, &#39;Too big error&#39;);```Example: Stacked Auto-Encoders---------------------```matlabfunction test_example_SAEload mnist_uint8;train_x = double(train_x)/255;test_x = double(test_x)/255;train_y = double(train_y);test_y = double(test_y);%% ex1 train a 100 hidden unit SDAE and use it to initialize a FFNN% Setup and train a stacked denoising autoencoder (SDAE)rand(&#39;state&#39;,0)sae = saesetup([784 100]);sae.ae{1}.activation_function = &#39;sigm&#39;;sae.ae{1}.learningRate = 1;sae.ae{1}.inputZeroMaskedFraction = 0.5;opts.numepochs = 1;opts.batchsize = 100;sae = saetrain(sae, train_x, opts);visualize(sae.ae{1}.W{1}(:,2:end)&#39;)% Use the SDAE to initialize a FFNNnn = nnsetup([784 100 10]);nn.activation_function = &#39;sigm&#39;;nn.learningRate = 1;nn.W{1} = sae.ae{1}.W{1};% Train the FFNNopts.numepochs = 1;opts.batchsize = 100;nn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.16, &#39;Too big error&#39;);```Example: Convolutional Neural Nets---------------------```matlabfunction test_example_CNNload mnist_uint8;train_x = double(reshape(train_x&#39;,28,28,60000))/255;test_x = double(reshape(test_x&#39;,28,28,10000))/255;train_y = double(train_y&#39;);test_y = double(test_y&#39;);%% ex1 Train a 6c-2s-12c-2s Convolutional neural network %will run 1 epoch in about 200 second and get around 11% error. %With 100 epochs you&#39;ll get around 1.2% errorrand(&#39;state&#39;,0)cnn.layers = { struct(&#39;type&#39;, &#39;i&#39;) %input layer struct(&#39;type&#39;, &#39;c&#39;, &#39;outputmaps&#39;, 6, &#39;kernelsize&#39;, 5) %convolution layer struct(&#39;type&#39;, &#39;s&#39;, &#39;scale&#39;, 2) %sub sampling layer struct(&#39;type&#39;, &#39;c&#39;, &#39;outputmaps&#39;, 12, &#39;kernelsize&#39;, 5) %convolution layer struct(&#39;type&#39;, &#39;s&#39;, &#39;scale&#39;, 2) %subsampling layer};cnn = cnnsetup(cnn, train_x, train_y);opts.alpha = 1;opts.batchsize = 50;opts.numepochs = 1;cnn = cnntrain(cnn, train_x, train_y, opts);[er, bad] = cnntest(cnn, test_x, test_y);%plot mean squared errorfigure; plot(cnn.rL);assert(er<0.12, &#39;Too big error&#39;);```Example: Neural Networks---------------------```matlabfunction test_example_NNload mnist_uint8;train_x = double(train_x) / 255;test_x = double(test_x) / 255;train_y = double(train_y);test_y = double(test_y);% normalize[train_x, mu, sigma] = zscore(train_x);test_x = normalize(test_x, mu, sigma);%% ex1 vanilla neural netrand(&#39;state&#39;,0)nn = nnsetup([784 100 10]);opts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samples[nn, L] = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.08, &#39;Too big error&#39;);%% ex2 neural net with L2 weight decayrand(&#39;state&#39;,0)nn = nnsetup([784 100 10]);nn.weightPenaltyL2 = 1e-4; % L2 weight decayopts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, &#39;Too big error&#39;);%% ex3 neural net with dropoutrand(&#39;state&#39;,0)nn = nnsetup([784 100 10]);nn.dropoutFraction = 0.5; % Dropout fraction opts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, &#39;Too big error&#39;);%% ex4 neural net with sigmoid activation functionrand(&#39;state&#39;,0)nn = nnsetup([784 100 10]);nn.activation_function = &#39;sigm&#39;; % Sigmoid activation functionnn.learningRate = 1; % Sigm require a lower learning rateopts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, &#39;Too big error&#39;);%% ex5 plotting functionalityrand(&#39;state&#39;,0)nn = nnsetup([784 20 10]);opts.numepochs = 5; % Number of full sweeps through datann.output = &#39;softmax&#39;; % use softmax outputopts.batchsize = 1000; % Take a mean gradient step over this many samplesopts.plot = 1; % enable plottingnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, &#39;Too big error&#39;);%% ex6 neural net with sigmoid activation and plotting of validation and training error% split training data into training and validation datavx = train_x(1:10000,:);tx = train_x(10001:end,:);vy = train_y(1:10000,:);ty = train_y(10001:end,:);rand(&#39;state&#39;,0)nn = nnsetup([784 20 10]); nn.output = &#39;softmax&#39;; % use softmax outputopts.numepochs = 5; % Number of full sweeps through dataopts.batchsize = 1000; % Take a mean gradient step over this many samplesopts.plot = 1; % enable plottingnn = nntrain(nn, tx, ty, opts, vx, vy); % nntrain takes validation set as last two arguments (optionally)[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, &#39;Too big error&#39;);```[![Bitdeli Badge](https://d2weczhvl823v0.cloudfront.net/rasmusbergpalm/deeplearntoolbox/trend.png)](https://bitdeli.com/free "Bitdeli Badge")

C# 12主构造函数新特性:如何让代码简洁度提升80%?

C# 12主构造函数让代码更简洁高效,解决传统构造函数冗余问题。适用于记录类型、服务类等场景,通过一行代码实现参数注入与字段初始化,显著提升可读性和开发效率。结合简化编程实践,大幅减少模板代码,值得收藏。

LiteCode的博客 775

主构造函数到底值不值得用?C# 12这一特性让代码瘦身80%

C# 12 主构造函数(Primary constructors)大幅简化类和结构体的初始化代码,适用于记录、DTO 和服务类等场景,减少样板代码达80%。通过在类型级别声明构造参数,实现字段自动赋值与作用域提升,提升可读性和开发效率。代码更整洁,维护更轻松,值得收藏。

CodeWhim的博客 861

揭秘C# 12主构造函数:如何彻底告别冗余构造代码?

C# 12主构造函数让代码更简洁,有效解决冗长构造逻辑问题。适用于记录类型、服务类等场景,通过一行声明自动初始化参数,显著提升开发效率。结合简化编程理念,减少样板代码,提升可读性与维护性,值得收藏。

FuncWander的博客 889

揭秘C# 12主构造函数:如何用一行代码简化类初始化逻辑

掌握C# 12主构造函数(Primary constructors),用一行代码简化类初始化逻辑,减少模板代码,提升开发效率。适用于记录类、DTO 和不可变对象,让构造参数自动成为公共属性。代码更简洁清晰,值得收藏。

SimProceed的博客 651

C# 12主构造函数全面解读:从语法糖到生产级应用的跃迁之路

掌握C# 12主构造函数在记录类型中的扩展与限制,提升代码简洁性与可维护性。详解其在不可变数据模型、构造函数参数推导中的应用,解析语法优势与使用边界,助力生产级高效开发。值得收藏。

QuickSolve的博客 690

C# 12主构造函数参数详解:为什么你应该立即升级并使用它?

掌握C# 12主构造函数参数简化代码新方式,提升开发效率。适用于记录类型、不可变对象等场景,减少模板代码,增强可读性与维护性。一文讲清语法用法与关键优势,值得收藏。

CompiShoal的博客 982

揭秘C# 12主构造函数底层机制:为什么你的基类参数总是传递失败?

深入解析C# 12主构造函数如何正确实现基类调用,解决参数传递失败问题。涵盖继承场景下的语法细节与编译优化机制,提升代码简洁性与可读性,值得收藏。

CodePulse的博客 868

掌握C# 12主构造函数的3个关键参数技巧(现代C#开发必知)

掌握C# 12主构造函数参数技巧,提升代码简洁性与可维护性。详解参数默认值、访问修饰符和属性注入三种用法,适用于现代C#开发中的实体类与服务注册场景。语法更清晰,减少样板代码,值得收藏。

VarLens的博客 995

【C# 12重磅更新】:主构造函数让类初始化变得前所未有的简单

C# 12主构造函数大幅简化类初始化流程,减少模板代码,提升开发效率。适用于实体类、DTO和配置对象等场景,通过一行代码完成参数注入与字段赋值,让C# 12主构造函数简化编程更直观高效,值得收藏。

CompiShoal的博客 898

揭秘C# 12主构造函数:为何它让记录类型更简洁、更高效?

掌握C# 12主构造函数在记录类型中的扩展,让代码更简洁高效。本文解析其在不可变数据模型和构造函数简化中的应用,提升类型安全与性能。通过实际示例展示核心用法与优势,值得收藏。

VarFun的博客 891
上一篇: 从零搭建cxx-qt项目:手把手教你规避90%初学者都会踩的坑
下一篇: 【C#跨平台性能监控终极指南】:揭秘高效监控工具设计原理与实战技巧
VarLens
博客等级 码龄1年 168粉丝 2188原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符  | 博主筛选后可见
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值