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

C#黑魔法:鸭子类型(Duck Typing)

C#黑魔法:鸭子类型(Duck Typing)

如果它走起路来像鸭子,叫起来像鸭子,那么它就是鸭子。

鸭子类型,主要应用于动态语言类型,比如JS、Python等,核心理念为:关注对象的行为(方法或属性)而非其具体类型。只要对象具备所需行为,即可在特定场景中使用,无需显式继承或实现接口。

来,在C#中使用鸭子类型魔法:

await 不必是 Task和ValueTask 对象

TPL是官推荐的C#异步编程模型,几乎所有提到TPL异步编程时,都必须是async配合await,等待一个Task或ValueTask.

事实上,并不是只有 Task 和 ValueTask 才能 await:只要符合下列条件的类,都能await

  1. 类中包含 GetAwaiter() 实例方法:返回一个实现了 INotifyCompletion 接口的 awaiter 对象
  2. 类中包含 bool类型的 IsCompleted 属性:用于告知 awaiter 是否已经完成了其操作
  3. 类中包含一个 OnCompleted 方法:
    说个秘密:.NET Core 中的 I/O 相关的异步 API 也的确是这么做的,I/O 操作过程中是不会有任何线程分配等待结果的,都是 coroutine 操作:I/O 操作开始后直接让出控制权,直到 I/O 操作完毕。

而之所以有的时候你发现 await 前后线程变了,那只是因为 Task 本身被调度了。

public class CustomTask<T>
{public CustomAwaiter<T> GetAwaiter(){return new CustomAwaiter<T>();}
}public class CustomAwaiter<T> : System.Runtime.CompilerServices.INotifyCompletion
{public bool IsCompleted { get; private set; }public T GetResult(){Console.WriteLine("获取异步结果");return default(T);}public void OnCompleted(Action continuation){Console.WriteLine("注册异步完成回调");IsCompleted = true;continuation?.Invoke();}
}var obj = new CustomTask<int>();
var r = await obj;
r.Display();

foreach 不必是 IEnumerable 和 IEnumerator 对象

满足以下条件的对象,就能使用 foreach:

  1. 类中只要有 GetEnumerator() 方法即可;
  2. GetEnumerator() 返回的对象包含一个 bool MoveNext() 方法加一个 Current 属性
//作为 GetEnumerator 方法的返回类
public class CustomEnumerator<T>
{public T Current { get; private set; }public bool MoveNext(){//这里写业务逻辑return false;}
}//只要有GetEnumerator方法,且返回值符合要求,就行了。
public class CustomEnumerable<T>
{public CustomEnumerator<T> GetEnumerator(){return new CustomEnumerator<T>();}
}//使用 foreach 查询
var names = new CustomEnumerable<string>();
foreach(var name in names)
{Console.WriteLine(name);
}

LINQ 不必是 IEnumerable对象

常见的Linq表达式语法:

var result = from q in source 
where q.StartsWith("s") 
select q; 

代码中的 source 的类型不一定非要实现 IEnumerable 接口。

事实上,只要有对应名字的方法就可以了。比如:有了名为 Select 的方法就能用 select,有了名为 Where 的方法就能用 where

public class Custom<TSource>
{private readonly TSource value;public Custom(TSource value) { this.value = value; }public Custom<TResult> Select<TResult>(Func<TSource, TResult> selector){if (value == null){throw new ArgumentNullException(nameof(value));}if (selector == null){throw new ArgumentNullException(nameof(selector));}return new Custom<TResult>(selector(value));}public Custom<TSource> Where(Func<TSource, bool> predicate){var r = predicate(value);if (r){return this;}else{return null;}}public new string ToString() => $"自定义Linq类: {value}";
}

上面 Custom 类,有了 Select 和 Where 方法,就可以使用 linq表达式 select 和 where

//声明对象
var source = new Custom<string>("select");//使用linq表达式查询
var qResult =  from m in source where m.StartsWith("s")select new { Name=source.ToString(), Age=1 };//结果(转化成一个匿名类)
Console.WriteLine(qResult.ToString());

using 对象, 不必实现 IDisposable接口

ref struct 因为必须在栈上且不能被装箱,所以不能实现接口。

只要 ref struct 对象中有一个 void Dispose() 方法,那么就可以用 using 语法实现对象的自动销毁。

//声明带 void Dispose()方法的引用类struct
ref struct MyRefStruct
{public string ToLower(string source){return source.ToLower();}public void Dispose(){//清理业务}
}//使用using语句,实现自动销毁
using (var myRef = new MyRefStruct())
{Console.WriteLine(myRef.ToLower("ABCEDF"));
}

普通类也能解构(非解析)

给一个普通类实现解构:只需要有一个名字为 Deconstruct() 的方法,并且参数都是 out 的即可。

class MyDeconstruct
{private int A => 1;private int B => 2;public void Deconstruct(out int a, out int b){a = A;b = B;}
}//实现解析操作
var x = new MyDeconstruct();
var (o, u) = x;
Console.WriteLine($"解构后,o={o},u={u}");

相关文章:

C#黑魔法:鸭子类型(Duck Typing)

C#黑魔法&#xff1a;鸭子类型(Duck Typing) 如果它走起路来像鸭子&#xff0c;叫起来像鸭子&#xff0c;那么它就是鸭子。 鸭子类型&#xff0c;主要应用于动态语言类型&#xff0c;比如JS、Python等&#xff0c;核心理念为&#xff1a;关注对象的行为&#xff08;方法或属性…...

AI数据分析中的伪需求场景:现状、挑战与突破路径

在当今企业数字化转型浪潮中&#xff0c;AI数据分析产品如雨后春笋般涌现&#xff0c;但其中存在大量"伪需求场景"——看似创新实则难以落地的功能设计。本文将从技术限制、用户体验和商业价值三个维度&#xff0c;系统分析AI数据分析产品中常见的伪场景现象&#xf…...

大尺寸PCB如何重塑通信与新能源产业格局

在5G通信基站与新能源电站的机房内&#xff0c;一块块面积超过600mm600mm的PCB板正悄然推动着技术革命。作为电子设备的核心载体&#xff0c;大尺寸PCB凭借其高密度集成与复杂工艺&#xff0c;成为通信、能源等领域的“隐形功臣”。以猎板PCB为代表的厂商&#xff0c;凭借宽幅曝…...

base64与图片的转换和预览(高阶玩法)

1.完整的功能描述 功能概述 这是一个网页工具&#xff0c;支持用户输入不同格式的图片数据或上传本地图片文件&#xff0c;对图片进行预览、转换为多种格式&#xff0c;并支持导出不同格式的图片数据。 输入方式 1. 文本输入 &#xff1a;用户可以输入 Data URL、公网图片 UR…...

AI客服问答自动生成文章(基于deepseek实现)

小编一直在用AI做网站平台文章的润色或者二创。一直有一个想法&#xff0c;在自己网站加一个AI智能客服&#xff0c;通过文心或者deepseek来智能回答网友提出的问题&#xff0c;这样就能减少很多人工回复的麻烦&#xff0c;提高互动效率。 开发背景 其实很多网友提出的问题非…...

Langchain、RAG、Agent相关

ChatBot-销售型机器人 优化点&#xff1a;把相似度低于10条的请求Query打印出来。 RAG 类型&#xff1a;RAG、Latent RAG&#xff08;产生一个回答&#xff0c;再用回答进行召回&#xff09;、Logit RAG、Speculative RAG 个人感觉RAG召回可以分成3种&#xff1a;一种是que…...

Spring Web MVC基础理论和使用

目录 什么是MVC 什么是SpringMVC SpringMVC基础使用 建立连接 RequestMapping介绍 请求 传递参数 传递对象 参数重命名 传递数组 传递JSON数据 获取URL中参数 上传文件 获取Cookie/Session 获取Header 响应 返回静态页面 RestController和Controller的区别 返…...

课程审核流程揭秘:确保内容合规与用户体验

业务流程 为什么课程审核通过才可以发布呢&#xff1f; 这样做为了防止课程信息有违规情况&#xff0c;课程信息不完善对网站用户体验也不好&#xff0c;课程审核不仅起到监督作用&#xff0c;也是 帮助教学机构规范使用平台的手段。 如果流程复杂用工作流 说明如下&#xff…...

Mac电脑,idea突然文件都展示成了文本格式,导致ts,tsx文件都不能正常加载或提示异常,解决方案详细说明如下

有一天使用clean my mac软件清理电脑 突然发现idea出现了文件都以文本格式展示&#xff0c;如图所示 然后就卸载&#xff0c;计划重新安装&#xff0c;安装了好几个版本&#xff0c;并且setting->file types怎么设置都展示不对&#xff0c;考虑是否idea没卸载干净&#xff…...

HarmonyOS开发-组件市场

1. HarmonyOS开发-组件市场 HarmonyOS NEXT开源组件市场是一个独立的插件&#xff0c;需通过DevEco Studio进行安装&#xff0c;可以点击下载&#xff0c;无需解压&#xff0c;直接通过zip进行安装&#xff0c;具体安装和使用方法可参考HarmonyOsNEXT组件市场使用说明。Harmony…...

【Python 列表(List)】

Python 中的列表&#xff08;List&#xff09;是最常用、最灵活的有序数据集合&#xff0c;支持动态增删改查操作。以下是列表的核心知识点&#xff1a; 一、基础特性 有序性&#xff1a;元素按插入顺序存储可变性&#xff1a;支持增删改操作允许重复&#xff1a;可存储重复元…...

vison transformer vit 论文阅读

An Image is Worth 16x16 Words 20年的论文看成10年的哈斯我了 [2010.11929] 一张图像胜过 16x16 个单词&#xff1a;用于大规模图像识别的转换器 --- [2010.11929] An Image is Worth 16x16 Words: Transformers for Image Recognition at Scale 为什么transformer好训练&am…...

图像移动图像归类代码

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 图像移动图像归类代码 import os import shutilvalue_dir rJ:\IDM_data\cls_chinese_medicine\cls_chinese_medicine\traintrain_dir rJ:\IDM_data\cls_chinese_medicine\c…...

Day 15 训练

Day 15 对鸢尾花数据集进行处理&#xff0c;特征可视化&#xff0c;贝叶斯优化随机森林&#xff0c;Shap解释1. 导入必要的库2. 设置中文字体3. 加载数据集4. 查看数据5. 数据准备6. 贝叶斯优化随机森林7. 评估结果8. 绘制箱形图9. 绘制特征相关性热力图10. SHAP模型解释总结 对…...

Vue Router 3 使用详解:从零构建嵌套路由页面

Vue Router 是 Vue.js 官方的路由管理器&#xff0c;常用于构建单页面应用&#xff08;SPA&#xff09;。本文将手把手带你完成 vue-router3.6.5 的基本配置&#xff0c;并实现一个带有嵌套路由的页面结构。本文适用于 Vue 2.x 项目 一、安装 vue-router3.6.5 npm install vue…...

物理服务器紧急救援:CentOS系统密码重置全流程实战指南

前言 在企业IT运维实践中&#xff0c;物理服务器密码丢失是典型的"低概率高风险"事件。某金融科技公司曾因核心服务器密码遗失导致业务中断36小时&#xff0c;直接损失超过800万元。这起真实案例揭示了系统密码管理的关键性——当承载重要业务的物理服务器遭遇密码丢…...

第J7周:对于ResNeXt-50算法的思考

目录 思考 一、代码功能分析 1. 构建 shortcut 分支&#xff08;残差连接的旁路&#xff09; 2. 主路径的第一层卷积&#xff08;11&#xff09; 4. 主路径的第三层卷积&#xff08;11&#xff09; 5. 残差连接 激活函数 二、问题分析总结&#xff1a;残差结构中通道数不一致的…...

华为云短信接入实现示例

1&#xff09;构建Springboot项目 2) 添加依赖 <dependency><groupId>com.huawei.apigateway</groupId><artifactId>java-sdk-core</artifactId><version>3.2.4</version> </dependency> 3) 配置文件 huaweiyun:sms:url:…...

Linux系统下使用Kafka和Zookeeper

Apache Kafka 是一个分布式流处理平台,最初由 LinkedIn 开发,后来成为 Apache 软件基金会的顶级项目。它具有高吞吐量、可扩展性、持久性、容错性等特点,主要用于处理实时数据流。 Linux系统下使用Kafka 1.安装 Java Kafka 和 Zookeeper 都是基于 Java 开发的,所以需要先…...

Unity按钮事件冒泡

今天unity写程序时&#xff0c;我做了一个透明按钮&#xff0c;没图片&#xff0c;只绑了点击事件&#xff0c;把子对象文字组件也删了&#xff0c;空留一个透明按钮&#xff0c;此时运行时点击按钮是没有反应的&#xff0c;网上的教程说必须指定target graphic&#xff08;目标…...

指令图像编辑模型:ICEdit-MoE-LoRA

ICEdit-MoE-LoRA 一、研究背景与目标 In-Context Edit 是一种新颖的基于指令的图像编辑方法&#xff0c;旨在实现与现有最佳方法相当甚至更优的编辑效果。传统图像编辑技术在处理复杂指令时存在一定局限性&#xff0c;尤其是在多轮编辑任务中&#xff0c;结果的准确性和连贯性…...

第十六届蓝桥杯 2025 C/C++B组第一轮省赛 全部题解(未完结)

目录 前言&#xff1a; 试题A&#xff1a;移动距离 试题C&#xff1a;可分解的正整数 试题D&#xff1a;产值调整 试题E&#xff1a;画展布置 前言&#xff1a; 我参加的是第一轮省赛&#xff0c;说实话第一次参加还是比较紧张的&#xff0c;真到考场上看啥都想打暴力&…...

捌拾叁- 量子傅里叶变换

1. 前言 最近公司地震&#xff0c;现在稍微有点时间继续学习。 看了几个算法&#xff0c;都说是基于 量子傅里叶变换 &#xff0c;好&#xff0c;就是他了 Quantum Fourier。 2. 傅里叶变换 大学是学通信的&#xff0c;对于傅里叶变换还是有所理解的。其实就是基于一个 时域…...

2.在Openharmony写hello world

原文链接&#xff1a;https://kashima19960.github.io/2025/03/21/openharmony/2.在Openharmony写hello%20world/ 前言 Openharmony 的第一个官方例程的是教你在Hi3861上编写hello world程序&#xff0c;这个例程相当简单编写 Hello World”程序&#xff0c;而且步骤也很省略&…...

STM32外设-串口UART

STM32外设-串口UART 一&#xff0c;串口简介二&#xff0c;串口基础概念1&#xff0c;什么是同步和异步/UART与USART对比2&#xff0c;串行与并行3&#xff0c;波特率 (Baud Rate)4&#xff0c;数据帧 (Data Frame)5&#xff0c;TX 和 RX 三&#xff0c;硬件连接1&#xff0c;u…...

计算机视觉与深度学习 | 视觉+激光雷达+惯惯性SLAM算法汇总(原理,公式,代码)

视觉+激光雷达+惯性 1. LVI-SAM(Laser-Visual-Inertial SLAM)2. MMF-LVINS(Multi-Modal Feature-based LVINS)3. FAST-LIVO(Fast LiDAR-Inertial-Visual Odometry)4. CamVox5. Coco-LIC6. FAST-LIO27. SLICT(Surfel-Based LiDAR-Inertial Mapping)总结与对比以下是对视…...

MCU存储系统架构解析

今天和大家分享一下MCU存储器层次结构的设计思路。这种分层存储架构通过整合不同特性的存储单元&#xff0c;能够很好地平衡性能与成本需求。 首先是寄存器层&#xff0c;它直接集成在CPU内核里&#xff0c;速度最快&#xff08;纳秒级&#xff09;&#xff0c;但容量比较小&a…...

使用mindie部署qwen2_vl分析视频

说明 使用mindie1.0部署qwen2_vl_72b模型&#xff0c;可以用来分析图片了。现在想分析视频。看了下mindie文档&#xff0c;支持视频分析的。 错误 错误1&#xff1a;没安装pyav http返回 Error code: 422 - {error: Messages token length must be in (0, 1048576], but g…...

Linux——MySQL基础

基础知识 连接服务器 mysql -h 127.0.0.1 -P 3306 -u root -p -h 指明登录部署了myqsl服务的主机 -P 指明访问的端口号 -u 指明用户 -p 指明登录密码&#xff08;可以不填写&#xff09; 什么是数据库 首先&#xff0c;数据库是分为服务端和客户端的&#xff1a; mysql是客户…...

Unity3D项目功耗与发热优化方案

前言 在Unity3D项目中&#xff0c;功耗和发热问题直接影响用户体验&#xff08;如设备发烫、续航下降&#xff09;&#xff0c;尤其在移动端设备上更为关键。以下是系统的分析与优化方案&#xff1a; 对惹&#xff0c;这里有一个游戏开发交流小组&#xff0c;大家可以点击进来…...