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

如何在 C# 12 中使用主构造函数 C# 12 中的主构造函数可用于类和结构以及记录类型。以下是它们如何使您的代码更干净、更简洁。 阅读详情

第一章:C# 12主构造函数概述

C# 12 引入了主构造函数(Primary Constructors)这一重要语言特性,旨在简化类型定义中的构造逻辑,提升代码的简洁性与可读性。该特性允许在类、结构体或记录的声明处直接定义构造参数,并将其用于初始化成员字段或属性,从而减少模板代码。

语法结构

主构造函数通过在类名后添加参数列表来声明,这些参数可在整个类型体内被访问。其典型用法如下:
// 使用主构造函数定义一个简单类
public class Person(string name, int age)
{
    public string Name { get; set; } = name;
    public int Age { get; set; } = age;

    public void Introduce()
    {
        Console.WriteLine($"Hello, I'm {Name}, {Age} years old.");
    }
}
上述代码中,string name 和 int age 是主构造函数的参数,它们被用于初始化属性。编译器会自动生成相应的私有字段并绑定到这些参数。

适用场景与优势

  • 减少样板代码:无需显式编写构造函数体和字段赋值语句
  • 增强可读性:构造意图在类型声明时即清晰表达
  • 支持记录和结构体:不仅适用于类,也可用于 record 和 struct

限制条件

限制项说明
必须使用括号包围参数即使无参数也需写成 ()
不能与传统实例构造函数共存若定义了主构造函数,则不能再定义同级的非静态构造函数
主构造函数是 C# 持续演进中对“简洁优先”编程范式的进一步支持,特别适合数据承载类型或配置类的设计。

第二章:主构造函数的基础语法与核心机制

2.1 主构造函数的语法结构与编译原理

在 Kotlin 中,主构造函数是类声明的一部分,位于类名之后,使用 `constructor` 关键字定义。它不包含任何代码块,仅用于参数声明和初始化逻辑的绑定。
基本语法结构
class User constructor(name: String, age: Int) {
    val name: String = name
    val age: Int = age
}
上述代码中,`constructor` 明确声明了主构造函数,接收两个参数。编译器会将其参数传递给属性初始化过程。若类无注解或可见性修饰符,`constructor` 关键字可省略。
编译期处理机制
Kotlin 编译器将主构造函数转换为 JVM 字节码中的类构造方法 ``。所有属性的初始化语句按声明顺序插入该方法体中。例如:
  • 参数被隐式提升为类的字段(若用 val 或 var 声明)
  • 默认值在字节码中生成为构造函数内的常量赋值
  • 初始化块(init)按出现顺序合并至主构造逻辑流

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

在现代编程语言设计中,主构造函数(Primary Constructor)逐渐成为简化对象初始化的主流方式,尤其在 Kotlin 和 C# 等语言中广泛应用。相较之下,传统构造函数需显式定义多个重载方法以支持不同参数组合。
语法简洁性对比
主构造函数将参数声明与类定义融合,显著减少模板代码:

class User(val name: String, val age: Int)
上述 Kotlin 代码自动创建字段并生成初始化逻辑。而传统方式如 Java 需手动编写构造函数、字段和 getter/setter:

public class User {
    private String name;
    private int age;
    public User(String name, int age) {
        this.name = name;
        this.age = age;
    }
}
核心差异总结
  • 主构造函数提升声明效率,降低冗余代码量
  • 传统构造函数灵活性高,适合复杂初始化流程
  • 主构造函数依赖语言特性支持,可读性强但控制粒度较粗

2.3 参数传递与字段初始化的底层实现

在方法调用过程中,参数传递的底层机制直接影响字段初始化的行为。JVM通过栈帧管理局部变量与操作数栈,实参值被压入调用方的操作数栈,随后由被调用方法的局部变量表接收。
值传递与引用传递的区别
Java始终采用值传递。对于基本类型,传递的是实际值的副本;对于对象,则是引用地址的副本。

public void initialize(Person p, int id) {
    p.name = "Alice";  // 修改引用指向对象的内容
    id = 100;          // 修改局部副本,不影响原变量
}
上述代码中,p 的修改会影响外部对象,而 id 的变更仅作用于栈帧内的局部变量。
字段初始化时序
对象创建时,JVM按以下顺序执行:
  1. 默认初始化(零值)
  2. 显式字段初始化或初始化块
  3. 构造函数中的逻辑
此过程确保了字段在参数注入前具备确定状态。

2.4 主构造函数在记录类型(record)中的应用实践

主构造函数简化对象创建
C# 中的记录类型(record)结合主构造函数,可显著简化不可变类型的定义。通过在类型声明中直接定义构造参数,字段初始化自动完成。
public record Person(string FirstName, string LastName);
上述代码中,Person 记录类型使用主构造函数声明两个参数,编译器自动生成只读属性、构造函数、以及重写的 Equals 和 ToString 方法。
支持自定义逻辑扩展
尽管主构造函数提供简洁语法,仍允许添加自定义验证逻辑:
public record Person(string FirstName, string LastName)
{
    public Person : this(FirstName ?? throw new ArgumentNullException(nameof(FirstName)),
                        LastName ?? throw new ArgumentNullException(nameof(LastName)))
    {
    }
}
该实现确保参数非空,增强类型安全性。主构造函数与记录类型的语义匹配,适用于数据承载场景,如 DTO、消息传递和函数式编程中的值对象。

2.5 可见性控制与私有化主构造函数的技巧

在Go语言中,可见性由标识符首字母大小写决定。小写标识符仅在包内可见,大写则对外公开。这一机制天然支持封装,是控制类型暴露程度的核心手段。
私有化主构造函数
通过将结构体定义为非导出类型,并提供导出的工厂函数,可实现构造逻辑的封装:

type database struct {
    conn string
}

func NewDatabase(conn string) *database {
    if conn == "" {
        conn = "default://localhost:5432"
    }
    return &database{conn: conn}
}
上述代码中,database 为私有结构体,外部无法直接实例化。而 NewDatabase 作为公共构造入口,可统一处理默认值与校验逻辑,增强安全性与一致性。

第三章:主构造函数的高级应用场景

3.1 在依赖注入中简化服务类的构造设计

在现代应用开发中,服务类往往依赖多个协作组件。手动实例化这些依赖会导致代码耦合度高、测试困难。依赖注入(DI)通过外部容器管理对象生命周期,自动注入所需依赖,显著简化构造逻辑。
构造函数注入示例

type UserService struct {
    repo UserRepository
    mail EmailService
}

func NewUserService(repo UserRepository, mail EmailService) *UserService {
    return &UserService{repo: repo, mail: mail}
}
上述代码通过构造函数注入 UserRepository 和 EmailService,使 UserService 无需关心依赖的创建过程,提升可测试性与模块化。
依赖注入的优势对比
场景传统方式依赖注入
对象创建硬编码于类内部由容器统一管理
测试难度需真实依赖可注入模拟对象

3.2 结合表达式体成员实现更简洁的类定义

在C#中,表达式体成员允许以更简洁的语法定义方法、属性和访问器,显著提升代码可读性。
语法简化示例
public class Person
{
    private string firstName;
    private string lastName;

    public string FullName => $"{firstName} {lastName}";

    public override string ToString() => FullName;
}
上述代码中,FullName 使用表达式体属性直接返回拼接结果,ToString() 方法也通过箭头语法省略了传统的大括号与 return 语句,使逻辑一目了然。
适用成员类型
  • 只读属性:使用 => 替代完整 get 块
  • 方法:适用于单行逻辑的方法体
  • 构造函数与终结器:也可使用表达式体(如 Person(string name) => this.Name = name;)
这种风格尤其适合不可变类型和数据容器类,使代码更加紧凑且语义清晰。

3.3 主构造函数与只读结构体的协同优化

在高性能场景下,主构造函数与只读结构体的结合能显著提升类型初始化效率并保证状态不可变性。通过构造函数直接初始化只读字段,避免了额外的赋值开销。
构造时初始化只读成员
public readonly struct Point
{
    public double X { get; }
    public double Y { get; }

    public Point(double x, double y) => (X, Y) = (x, y);
}
上述代码中,结构体被声明为 readonly,所有字段在构造函数中一次性赋值。由于结构体不可变,编译器可进行内联优化,减少副本操作。
性能优势对比
模式内存拷贝次数线程安全性
普通结构体3低
只读结构体 + 主构造函数1高
只读结构体配合主构造函数,使数据在传递过程中无需防御性拷贝,提升了缓存命中率和并发访问安全性。

第四章:性能优化与最佳实践

4.1 减少冗余代码提升类声明可读性

在大型应用开发中,类声明常因重复属性和方法而变得臃肿。通过提取共用逻辑、使用组合优于继承等设计原则,可显著提升可读性与维护性。
使用嵌入类型消除重复字段
Go语言中可通过嵌入(embedding)机制复用结构体字段,避免手动复制粘贴。
type User struct {
    ID   int
    Name string
}

type Admin struct {
    User  // 嵌入User,自动获得ID和Name
    Role string
}
上述代码中,Admin 直接嵌入 User,无需重新声明相同字段。访问时既可直接调用 admin.Name,也可通过 admin.User.Name 显式访问,增强语义清晰度。
接口抽象共用行为
定义统一接口规范行为,减少重复方法实现:
  • 声明接口隔离变化点
  • 具体类型实现接口,避免逻辑拷贝
  • 便于后期扩展与测试

4.2 避免常见陷阱:循环引用与参数验证

警惕结构体间的循环引用
在定义嵌套结构体时,若两个结构体相互包含,将导致编译错误或内存泄漏。应通过指针引用打破循环依赖。
强化参数验证机制
在构造函数或初始化方法中加入参数校验逻辑,防止传入 nil 或非法值引发运行时异常。
  • 检查输入参数是否为 nil
  • 验证数值范围与边界条件
  • 确保字符串非空且格式合法

func NewUser(name string, age int) (*User, error) {
    if name == "" {
        return nil, fmt.Errorf("name cannot be empty")
    }
    if age < 0 || age > 150 {
        return nil, fmt.Errorf("age must be between 0 and 150")
    }
    return &User{Name: name, Age: age}, nil
}
上述代码在创建 User 实例前对 name 和 age 进行有效性验证,避免非法状态的产生。错误提前暴露有助于提升系统稳定性。

4.3 在大型项目中统一构造逻辑的设计模式

在复杂系统中,对象的创建逻辑容易散落在多处,导致维护困难。通过引入**工厂模式**与**构建者模式**的组合,可实现构造逻辑的集中化管理。
工厂封装类型创建

type ServiceFactory struct {
    config *Config
}

func (f *ServiceFactory) CreateUserService() *UserService {
    db := f.config.GetDB()
    logger := f.config.GetLogger()
    return &UserService{db: db, logger: logger}
}
上述代码将 UserService 的依赖注入统一由工厂完成,避免重复初始化逻辑。
构建者处理复杂参数
对于参数繁多的对象,使用构建者模式分步构造:
  • 通过链式调用设置可选参数
  • 最终调用 Build() 方法生成实例
  • 保证对象始终处于有效状态
两种模式结合,显著提升代码可读性与扩展性。

4.4 编译时优化与IL代码生成效率分析

在.NET编译过程中,C#源码首先被编译为中间语言(IL),再通过JIT转换为本地机器码。编译器在生成IL时会执行多项优化策略,显著影响最终执行效率。
常见编译时优化技术
  • 常量折叠:在编译期计算常量表达式,减少运行时开销
  • 死代码消除:移除不可达或无副作用的代码路径
  • 内联展开:将小函数体直接嵌入调用处,降低调用开销
IL生成优化示例

// 原始代码
int result = 2 * 3 + x;

// 优化后IL等效逻辑(常量折叠)
int result = 6 + x;
上述代码中,2 * 3在编译期即被计算为6,避免了运行时算术运算,提升执行效率。
优化效果对比
优化类型性能增益适用场景
常量折叠高数学表达式
死代码消除中条件编译分支
方法内联高小型辅助函数

第五章:总结与未来展望

边缘计算与AI模型的协同演进
随着物联网设备数量激增,边缘侧推理需求显著上升。将轻量级模型部署至边缘网关已成为主流方案。例如,在工业质检场景中,使用TensorFlow Lite在树莓派上运行YOLOv5s量化模型,实现毫秒级缺陷识别:

# 加载TFLite模型并进行推理
interpreter = tf.lite.Interpreter(model_path="yolov5s_quant.tflite")
interpreter.allocate_tensors()
input_details = interpreter.get_input_details()
interpreter.set_tensor(input_details[0]['index'], input_data)
interpreter.invoke()
detections = interpreter.get_tensor(interpreter.get_output_details()[0]['index'])
云原生架构下的可观测性增强
现代系统依赖多层次监控体系。下表展示了典型微服务架构中的关键指标采集策略:
组件类型监控指标采集工具
API网关请求延迟、QPSPrometheus + Envoy Stats
Kubernetes PodCPU/内存使用率cAdvisor + Metrics Server
消息队列积压消息数、消费延迟Kafka Exporter
  • 分布式追踪需覆盖跨服务调用链,建议采用OpenTelemetry SDK注入上下文
  • 日志结构化应遵循JSON格式规范,便于ELK栈解析与告警匹配
  • 服务网格可自动注入sidecar代理,实现零代码改造的流量观测
未来,AIOps平台将整合异常检测算法,基于历史时序数据预测容量瓶颈,动态触发HPA扩缩容策略。
手把手教你从入门到精通C#串口通信 本文以我开发的串口助手SComTool为例,详细介绍《C#串口通信从入门到精通》专栏的目录内容,本专栏由一个高级工程师多年实战经验总结,绝对是c#串口通信的葵花宝典!带您从入门到精通C#串口通信! 阅读详情

相关推荐

Cadence Spectre仿真保姆级教程:从DC/AC到PSS/PV,手把手教你搞定模拟电路分析

作为业界标准的Cadence Spectre仿真器,以其精确的算法和丰富的分析类型,成为每个模拟IC工程师必须掌握的利器。本文将带你从零开始,系统掌握Spectre仿真的核心技能,从最基础的DC工作点分析到复杂的PSS相位噪声仿真,每个步骤都配有详细的操作指导和实用技巧。记得我第一次使用Spectre仿真一个简单的两级运放时,花了整整三天时间才得到正确的AC响应曲线。过程中踩过的坑、浪费的时间,现在想来都是宝贵的学习资源。与传统的AC分析不同,STB分析可以在不破坏环路的情况下评估稳定性。

weixin_30898555的博客 335

【C#语言】主构造函数

在 C# 中,构造函数是一种特殊的方法,用于在创建对象时初始化对象的状态。而主构造函数,作为构造函数中的 “主力军”,更是承担着主要的初始化职责。它是类或结构体中声明的第一个构造函数,通常用于执行对象创建时最核心的初始化操作。与普通构造函数相比,主构造函数有着独特的地位和作用。普通构造函数可以有多个,它们之间通过参数列表的不同来实现重载,以满足不同的初始化需求。而主构造函数在一个类或结构体中只有一个,它是对象初始化的 “入口”,为对象的后续使用奠定基础。

远程部署调试 运行安装 项目调试 二次开发 项目技术新 持续迭代 部分源码免费分享 1568

Qt中常见的面试题总结

基于Qt开发的一些常用面试题

一名热爱编程的程序员 8493

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

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

鲤籽鲲的博客 1652

手把手教你用u-center配置ublox GPS模块:从波特率到报文频率全流程

本文提供了一份详细的u-center软件配置ublox GPS模块的完整指南。从硬件连接到软件设置,逐步讲解了如何探测并设置正确的波特率、选择与启用关键的NMEA和UBX报文,以及配置输出频率。文章特别强调了配置固化的重要性,并分享了使用UBX协议进行高效数据解析等高级技巧,帮助开发者快速上手并优化GPS模块性能。

weixin_28285943的博客 897

Linux(31)Rockchip RK3568 Ubuntu22.04上部署 Docker: 问题与解决方案

本博客在总结这些问题及其解决方案,为遇到类似问题的兄弟提供参考,如果我后续有碰到其他Docker 问题也会在此更新补充。

我其实什么都不会 1646

C#从入门到精通:一场深入浅出的编程之旅【文末送书】

在当今数字化的时代,编程已经成为一项至关重要的技能。而在众多编程语言中,C#(C Sharp)因其强大的功能和广泛的应用领域而备受青睐。本文将带领读者从入门到精通,探索C#编程语言的奥秘,助力读者在编程的道路上踏出坚实的步伐。

一键难忘的博客 7229

Python爬虫实战:如何爬取12306列车信息

本文介绍了如何使用Python编写爬虫,抓取12306列车信息。我们讲解了如何分析12306的列车数据接口,如何发送HTTP请求,解析返回的JSON数据,并将数据保存到本地文件中。我们还讨论了如何绕过反爬虫机制,如使用随机User-Agent和设置请求延时。通过这个实战项目,你应该掌握了如何爬取并解析来自公共API的数据,同时提高了你的爬虫技能。这些技能不仅适用于12306列车信息抓取,也可以广泛应用于其他需要抓取JSON数据的网站。

2201_76125261的博客 1922

C#从入门到精通

C#从入门到精通

qq_46555046的博客 1万+

手把手教你学 Simulink (1.3):探索Simulink模块库的奇妙世界

Simulink模块库按照功能分为多个类别,每个类别包含专门用于特定任务的模块。% 打开Simulink库浏览器% 或者以编程方式获取库列表disp('可用的库列表:');end常用模块(Simulink):最基础和最常用的模块信号处理模块(DSP System Toolbox):专业信号处理工具通信模块(Communications Toolbox):通信系统设计控制系统模块(Control System Toolbox):控制系统设计与分析% 创建自定义模块库。

QQ_778132974的博客 384

OpenClaw 自定义 Skill 开发完整指南(最新版)

OpenClaw 中的每个 Skill,本质是一套“能力描述 + 执行逻辑”的组合包,核心特征如下:核心载体:以文件夹为单位,文件夹内必须包含SKILL.md文件(能力描述核心);扩展文件:可选agent.py(Python 执行逻辑)、index.ts(TypeScript 执行逻辑)、(辅助文档/示例资源)等;核心优势:AI 通过阅读 SKILL.md 的自然语言描述理解技能,无需严格遵循代码接口,灵活度极高;

haolove527的专栏 2万+

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

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

PoliVein的博客 721

IMSL CNL 7.0.0 (x86-64)Crack

IMSL CNL 7.0.0 (x86-64)Crack intel的算法库破解文件,这是C++版本的破解文件

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

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

InstrFun的博客 980

ET2012新版免狗免安装绿色软件

ET2012新版免狗免安祖昂绿色软件。,新界面,新视觉,

深度学习工具包 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# 代码

作者:David Pine排版:Alan Wang引入了一组引人注目的新功能!在这篇文章中,我们将探讨其中一个功能,特别是主构造函数,解释其用法和相关性。然后,我们将演示一个重构示例,以展示如何将其应用到您的代码中,并讨论其好处和潜在的缺陷。这将帮助您了解这一更改的影响并有助于您决定是否采用该功能。

MicrosoftReactor的博客 1127

LinePhone3.2.7(android端最新版本) sip客户端

SIP客户端For android:LinePhone3.2.7(最新版本),官网地址:http://www.linphone.org/

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

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

FastCompile的博客 797

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

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

GatherLume的博客 722

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

掌握C# 12主构造函数,三步实现代码极简主义,有效简化编程流程。适用于记录类型、依赖注入等场景,减少样板代码,提升开发效率。语法简洁,语义清晰,值得收藏。

VarLens的博客 650

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

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

CodePulse的博客 868

主构造函数真的万能吗?深入剖析C# 12记录类型的3大技术边界

掌握C# 12主构造函数在记录类型中的扩展与限制,提升代码简洁性与可维护性。详解适用场景、不可变类型构建及继承边界,揭示三大技术限制与最佳实践。深入理解语法优势与潜在陷阱,值得收藏。

ByteChat的博客 1000

C# 12主构造函数避坑指南,99%新手都会忽略的2个关键限制条件

掌握C# 12主构造函数(Primary constructors)的正确用法,避开常见陷阱。本文详解其在类和结构体中的适用场景,揭示只读字段初始化和重载限制两大关键条件,提升代码简洁性与安全性。避坑指南,值得收藏。

FuncTide的博客 661

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

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

VarLens的博客 995

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

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

QuickSolve的博客 690

C# 12主构造函数与只读属性实战指南(现代C#编程必备技能)

掌握C# 12主构造函数与只读属性的高效用法,提升代码简洁性与安全性。适用于记录类型、不可变对象等场景,简化初始化逻辑,增强类型封装。现代C#编程必备技能,值得收藏。

Instrulink的博客 907

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

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

CompiShoal的博客 982

C# 12 主构造函数实战:3种典型场景代码对比与性能影响分析

本文深入探讨了C# 12主构造函数在3种典型场景中的应用,包括依赖注入、不可变类型和记录类型,并通过代码对比与性能测试分析其优势。主构造函数显著简化了代码结构,提升了可读性,同时保持与传统构造函数相同的性能表现,是C#开发者的高效工具。

weixin_33922672的博客 493
上一篇: 顶级语句如何重塑你的C#开发效率,90%的人都还没用上
下一篇: 【.NET开发效率提升】:using别名在复杂项目中的4种高阶用法
StepLens
博客等级 码龄1年 149粉丝 2031原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符  | 博主筛选后可见
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值