在 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 类的更多相关文章

  1. dotnet 读 WPF 源代码笔记 布局时 Arrange 如何影响元素渲染坐标

    大家是否好奇,在 WPF 里面,对 UIElement 重写 OnRender 方法进行渲染的内容,是如何受到上层容器控件的布局而进行坐标偏移.如有两个放入到 StackPanel 的自定义 UIEl ...

  2. dotnet 读 WPF 源代码笔记 渲染收集是如何触发

    在 WPF 里面,渲染可以从架构上划分为两层.上层是 WPF 框架的 OnRender 之类的函数,作用是收集应用程序渲染的命令.上层将收集到的应用程序绘制渲染的命令传给下层,下层是 WPF 的 GF ...

  3. 读Flask源代码学习Python--config原理

    读Flask源代码学习Python--config原理 个人学习笔记,水平有限.如果理解错误的地方,请大家指出来,谢谢!第一次写文章,发现好累--!. 起因   莫名其妙在第一份工作中使用了从来没有接 ...

  4. [WPF源代码]QQ空间相册下载工具

    放一个WPF源代码,源代码地址 http://download.csdn.net/detail/witch_soya/6195987 代码没多少技术含量,就是用WPF做的一个QQ空间相册下载工具,效果 ...

  5. 《深入浅出WPF》笔记——绘画与动画

    <深入浅出WPF>笔记——绘画与动画   本篇将记录一下如何在WPF中绘画和设计动画,这方面一直都不是VS的强项,然而它有一套利器Blend:这方面也不是我的优势,幸好我有博客园,能记录一 ...

  6. 《深入浅出WPF》笔记——事件篇

    如果对事件一点都不了解或者是模棱两可的话,建议先去看张子阳的委托与事件的文章(比较长,或许看完了,也忘记看这一篇了,没事,我会原谅你的)http://www.cnblogs.com/JimmyZhan ...

  7. 《深入浅出WPF》笔记——资源篇

    原文:<深入浅出WPF>笔记--资源篇 前面的记录有的地方已经用到了资源,本文就来详细的记录一下WPF中的资源.我们平时的“资源”一词是指“资财之源”,是创造人类社会财富的源泉.在计算机程 ...

  8. 在Linux上编译dotnet cli的源代码生成.NET Core SDK的安装包

    .NET 的开源,有了更多的DIY乐趣.这篇博文记录一下在新安装的 Linux Ubuntu 14.04 上通过自己动手编译 dotnet cli 的源代码生成 .net core sdk 的 deb ...

  9. WPF学习笔记-用Expression Design制作矢量图然后导出为XAML

    WPF学习笔记-用Expression Design制作矢量图然后导出为XAML 第一次用Windows live writer写东西,感觉不错,哈哈~~ 1.在白纸上完全凭感觉,想象来画图难度很大, ...

  10. WPF 学习笔记-在WPF下创建托盘图标

    原文:WPF 学习笔记-在WPF下创建托盘图标 首先需要在项目中引用System.Windows.Forms,System.Drawing; using System; using System.Co ...

随机推荐

  1. 记录--实时音视频功能简析(live-pusher与live-player)

    这里给大家分享我在网上总结出来的一些知识,希望对大家有所帮助 使用须知 2017年下半年,微信6.5.21版本支持在线音视频功能.开发者可以通过两个音视频组件 和 实现实时地在线直播.视频通话.语音通 ...

  2. linux系统centos7.9如何安装nginx

    1.官网下载nginx nginx官网:https://nginx.org/ 选择稳定版进行下载,也可以下载老版本,下载成功后上传到服务器. 2.使用wget下载 访问nginx官网,在下载页面鼠标右 ...

  3. 郑州IT微信交流群期待你的加入

    我建了一个郑州IT微信交流群,找工作,找项目,人员招聘的都可以加入. 你有一个苹果,我有一个香蕉,合在一起,我们每个人都可以吃到两种水果了.广结人缘,扩大自己的人脉. 可以加我个人微信,拉你进群.

  4. #博弈论#Poj 2484 A Funny Game

    题目 \(n\)个石子排成一圈,每次可以取一个或相邻的一对, 取完为胜,问先手是否必胜 分析 无论先手如何取,后手都能模仿先手的取法. 比如说,当石子个数为奇数时先手取相邻的一对,后手可以将对面的那一 ...

  5. MySQL 主从 AUTO_INCREMENT 不一致问题分析

    作者:vivo 互联网数据库团队 - Wei Haodong 本文介绍了 MySQL5.7 中常见的replace into 操作造成的主从auto_increment不一致现象,一旦触发了主从切换, ...

  6. 大咖齐聚!OpenHarmony技术峰会豪华嘉宾阵容揭晓

      第一届开放原子开源基金会OpenHarmony技术峰会即将来袭 重量级嘉宾和行业大咖高能集结 展示OpenHarmony操作系统技术革新 1场主论坛.6场分论坛干货拉满 2月25日,一起解锁更多精 ...

  7. 高可用之战:Redis Sentinal(哨兵模式)

    ★ Redis24篇集合 1 背景 在我们的<Redis高可用之战:主从架构>篇章中,介绍了Redis的主从架构模式,可以有效的提升Redis服务的可用性,减少甚至避免Redis服务发生完 ...

  8. HDC2022 开发者亮点抢先看,线上线下精彩活动等你探索!

    原文:https://mp.weixin.qq.com/s/A2sfpPKBvF6zwinbUsgwiw,点击链接查看更多技术内容.

  9. Code Aesthetic

    01 Abstraction Abstraction is the process of aggregating code with high similarity among multiple cl ...

  10. Mysql系列:Mysql5.7编译安装--系统环境:Centos7 / CentOS9 Stream

    Mysql系列:Mysql5.7编译安装 系统环境:Centos7 / CentOS9 Stream 1:下载mysql源码包 https://dev.mysql.com/downloads/mysq ...