dotnet 读 WPF 源代码笔记 为什么加上 BooleanBoxes 类
在 WPF 框架,为什么需要定义一个 BooleanBoxes 类。为什么在 D3DImage 的 Callback 方法里面,传入的是 object 对象,却能被转换为布尔。本文将告诉大家为什么需要这样设计
大家都知道,在 dotnet 里面,如果将一个结构体通过 object 的方式传输,将需要进行装箱。而装箱将会创建一个新的对象。在 WPF 这个框架里面,有很多逻辑,例如消息,都是非常快速在调用的。如果每次调用,例如传输布尔值,由于需要进入很多框架逻辑,而让参数只能使用 object 类型,那么每次都使用结构体将需要多次的装箱,从而创建大量的对象
创建大量的对象将会让界面逻辑需要不断进行内存回收,自然性能就降低了
那为什么不设计一个泛形呢?因为代码将不好写,同时由于泛形类型的静态属性将不相同,从而再次让逻辑更加复杂。而且对于大多数逻辑来说,确实传输的只是引用对象,传输结构体还是一个比较少的业务。在 WPF 框架,为了解决此问题,于是就创建了 KnownBoxes 系列类型。包括 NullableBooleanBoxes 和 BooleanBoxes 类型。这两个类型将预先将布尔装箱,当成 object 对象。接下来,所有需要对布尔装箱的逻辑,都将使用 BooleanBoxes 的对象代替
以下代码是 BooleanBoxes 的逻辑
internal static class BooleanBoxes
{
internal static object TrueBox = true;
internal static object FalseBox = false;
internal static object Box(bool value)
{
if (value)
{
return TrueBox;
}
else
{
return FalseBox;
}
}
}
可以看到 BooleanBoxes 的 TrueBox 和 FalseBox 属性都是由布尔装箱创建的。为什么创建的方法是需要使用布尔装箱,而不是随便拿两个对象?原因是如此方便重新转换为布尔值
使用 BooleanBoxes 的性能如何?请看 https://github.com/dotnet/runtime/issues/7079#issuecomment-264500921

| Method | Mean | StdDev | Median | Scaled |
|---|---|---|---|---|
| BoolUncachedBoxing | 7.3923 ns | 0.0391 ns | 7.3866 ns | 1.00 |
| BoolCachedBoxing | 4.5859 ns | 0.0310 ns | 4.5954 ns | 0.62 |
那为什么在 dotnet 里面,不默认加上此优化呢?原因是如文档,每次在 dotnet 的装箱,都是生成新的对象。没错,新的对象。因此如果做此优化,将修改行为
那这和 D3DImage 的 Callback 方法里面,有什么关系呢?其实在此方法里面,调用到 SetIsFrontBufferAvailable 方法,在此方法里面进行了一次强转,于是我开始阅读代码,认为强转会炸,先来看看此方法做了什么
private object SetIsFrontBufferAvailable(object isAvailableVersionPair)
{
Pair pair = (Pair)isAvailableVersionPair;
uint version = (uint)pair.Second;
if (version == _version)
{
bool isFrontBufferAvailable = (bool)pair.First;
SetValue(IsFrontBufferAvailablePropertyKey, isFrontBufferAvailable);
}
// ...just because DispatcherOperationCallback requires returning an object
return null;
}
此方法的参数能拿到一个 Pair 类型的对象,然而此对象的两个值都是 object 类型,需要进行一次转换。然而在 Callback 方法里面,代码如下
private void Callback(bool isFrontBufferAvailable, uint version)
{
Dispatcher.BeginInvoke(
DispatcherPriority.Normal,
new DispatcherOperationCallback(SetIsFrontBufferAvailable),
new Pair(BooleanBoxes.Box(isFrontBufferAvailable), version)
);
}
可以看到在传入的参数,拿到的 Pair 的第一个参数,是用 BooleanBoxes 创建的。然而在 SetIsFrontBufferAvailable 方法里面,将此参数进行了强转。相当于 (bool) BooleanBoxes.Box(isFrontBufferAvailable) 的代码。我开始看到 BooleanBoxes 的 Box 返回的是一个 object 对象,以为对 object 对象进行强转肯定会炸。实际上这是不会炸的,转换是符合预期的
那为什么一个 object 对象,在 SetIsFrontBufferAvailable 能被转换为布尔呢?这就是 BooleanBoxes 的属性都是由布尔装箱创建的原因。因为本来是通过布尔装箱创建的,也因此能被转换为布尔值
以上就是 WPF 为什么加上 BooleanBoxes 类的原因,以及在 D3DImage 里,使用布尔强转一个 object 可以符合预期
更多逻辑,还请阅读 WPF 源代码
当前的 WPF 在 https://github.com/dotnet/wpf 完全开源,使用友好的 MIT 协议,意味着允许任何人任何组织和企业任意处置,包括使用,复制,修改,合并,发表,分发,再授权,或者销售。在仓库里面包含了完全的构建逻辑,只需要本地的网络足够好(因为需要下载一堆构建工具),即可进行本地构建
dotnet 读 WPF 源代码笔记 为什么加上 BooleanBoxes 类的更多相关文章
- dotnet 读 WPF 源代码笔记 布局时 Arrange 如何影响元素渲染坐标
大家是否好奇,在 WPF 里面,对 UIElement 重写 OnRender 方法进行渲染的内容,是如何受到上层容器控件的布局而进行坐标偏移.如有两个放入到 StackPanel 的自定义 UIEl ...
- dotnet 读 WPF 源代码笔记 渲染收集是如何触发
在 WPF 里面,渲染可以从架构上划分为两层.上层是 WPF 框架的 OnRender 之类的函数,作用是收集应用程序渲染的命令.上层将收集到的应用程序绘制渲染的命令传给下层,下层是 WPF 的 GF ...
- 读Flask源代码学习Python--config原理
读Flask源代码学习Python--config原理 个人学习笔记,水平有限.如果理解错误的地方,请大家指出来,谢谢!第一次写文章,发现好累--!. 起因 莫名其妙在第一份工作中使用了从来没有接 ...
- [WPF源代码]QQ空间相册下载工具
放一个WPF源代码,源代码地址 http://download.csdn.net/detail/witch_soya/6195987 代码没多少技术含量,就是用WPF做的一个QQ空间相册下载工具,效果 ...
- 《深入浅出WPF》笔记——绘画与动画
<深入浅出WPF>笔记——绘画与动画 本篇将记录一下如何在WPF中绘画和设计动画,这方面一直都不是VS的强项,然而它有一套利器Blend:这方面也不是我的优势,幸好我有博客园,能记录一 ...
- 《深入浅出WPF》笔记——事件篇
如果对事件一点都不了解或者是模棱两可的话,建议先去看张子阳的委托与事件的文章(比较长,或许看完了,也忘记看这一篇了,没事,我会原谅你的)http://www.cnblogs.com/JimmyZhan ...
- 《深入浅出WPF》笔记——资源篇
原文:<深入浅出WPF>笔记--资源篇 前面的记录有的地方已经用到了资源,本文就来详细的记录一下WPF中的资源.我们平时的“资源”一词是指“资财之源”,是创造人类社会财富的源泉.在计算机程 ...
- 在Linux上编译dotnet cli的源代码生成.NET Core SDK的安装包
.NET 的开源,有了更多的DIY乐趣.这篇博文记录一下在新安装的 Linux Ubuntu 14.04 上通过自己动手编译 dotnet cli 的源代码生成 .net core sdk 的 deb ...
- WPF学习笔记-用Expression Design制作矢量图然后导出为XAML
WPF学习笔记-用Expression Design制作矢量图然后导出为XAML 第一次用Windows live writer写东西,感觉不错,哈哈~~ 1.在白纸上完全凭感觉,想象来画图难度很大, ...
- WPF 学习笔记-在WPF下创建托盘图标
原文:WPF 学习笔记-在WPF下创建托盘图标 首先需要在项目中引用System.Windows.Forms,System.Drawing; using System; using System.Co ...
随机推荐
- 记录--vue3 setup 中国省市区三级联动options最简洁写法,无需任何库
这里给大家分享我在网上总结出来的一些知识,希望对大家有所帮助 在写页面的时候,发现表单里面有一个省市区的 options 组件要写,因为表单很多地方都会用到这个地址选择,我便以为很简单嘛. 虽然很简单 ...
- kali 2018.2镜像安装
本文链接来源 Kali Linux 前身是著名渗透测试系统BackTrack ,是一个基于 Debian 的 Linux 发行版,包含很多安全和取证方面的相关工具.此次通过VMware虚拟机安装201 ...
- JSON转换为CSV
<dependency> <groupId>org.json</groupId> <artifactId>json</artifactId> ...
- Oracle存储过程模板
PROCEDURE proc_test(p_id IN NUMBER, v_cur OUT SYS_REFCURSOR, p_result_code OUT NUMBER, p_result_mess ...
- verilog之monitor
verilog之monitor 1.函数作用 monitor用于追踪变量的变化情况,这在实际使用中还是非常实用的.电路中的某个信号的变化可以通过monitor检测,不需要使用波形图去仔细查找.也便于准 ...
- 自定义AXI总线IP之补全寄存器的输入输出配置
自定义AXI总线IP之补全寄存器配置输入和输出 1.实验目的 在使用默认的AXI4的配置时,不会有寄存器的配置,无法配置端口的输入还是输出.根据前面的AXI总线的理解,这里通过仲裁器判断,将AXI4的 ...
- KingbaseES错误分析 -- “requested character too large”
一.适用于: 本文档使用于KingbaseES所有版本. 二.问题现象: 使用从其他数据库迁移到KingbaseES数据库的自定义函数.存储过程.Package包..出现以下错误信息: 错误:所请求的 ...
- Games101-作业5
说明 本次作业主要实现Whitted-光线追踪,作业框架只需要我们编写两个部分,一个是求解观测光线--从摄像机到每个像素的向量:第二个是判断射线与三角形的交点. 求解观测光线 需要对每个像素求解在实际 ...
- linux 禁用休眠,挂起,睡眠
参照 https://www.cnblogs.com/minseo/p/13557947.html 禁用休眠前查看状态 systemctl status sleep.target suspend.ta ...
- 国民经济行业分类与代码(GB/T 4754-2017、GB/T 4754-2011、GB/T 4754-2002)数据下载
2002_2011_2017国民经济行业分类与代码mysql数据四级分类文件.rar 内容:其中包含2002.2011.2017三年国民经济行业分类和代码的MySQL文件,每一个表的格式如下:例如第一 ...