在 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. 上位机连接PLC

    上位机使用Hsl框架连接PLC 顺便讲下策略模式 话不多说,直接上代码 public interface IPlcHost { bool ConnectionPlc(string path); } p ...

  2. 记录-js基础练习题

    这里给大家分享我在网上总结出来的一些知识,希望对大家有所帮助 隔行换色(%): window.onload = function() { var aLi = document.getElementsB ...

  3. 【已解决】Windows环境下redis启动失败

    在redis安装目录下打开cmd窗口: 依次输入: redis-cli.exe shutdown exit redis-server.exe redis.windows.conf ps:启动失败可能是 ...

  4. 2024-04-06:用go语言,给你两个非负整数数组 rowSum 和 colSum, 其中 rowSum[i] 是二维矩阵中第 i 行元素的和, colSum[j] 是第 j 列元素的和,换言之你

    2024-04-06:用go语言,给你两个非负整数数组 rowSum 和 colSum, 其中 rowSum[i] 是二维矩阵中第 i 行元素的和, colSum[j] 是第 j 列元素的和,换言之你 ...

  5. 资讯速递 | ArkUI-X 预览版已正式开源!

     OpenHarmony项目群技术指导委员会(以下简称"TSC")-跨平台应用开发框架TSG所孵化项目 -- ArkUI-X,近期已正式开源 ,开发者基于一套主代码,就可以将在Op ...

  6. 深度解析 Spring Security:身份验证、授权、OAuth2 和 JWT 身份验证的完整指南

    Spring 安全框架 Spring Security 是一个用于保护基于 Java 的应用程序的框架.它是一个功能强大且高度可定制的身份验证和访问控制框架,可以轻松地集成到各种应用程序中,包括 We ...

  7. Redis和elasticsearch

    redis -----------NOSQL的对比和劣和应用场景参考好文http://www.redis.cn/articles/20181020003.html --------- -------- ...

  8. K8S 性能优化-K8S Node 参数调优

    前言 K8S 性能优化系列文章,本文为第四篇:Kubernetes Node 性能优化参数最佳实践. 系列文章: <K8S 性能优化 - OS sysctl 调优> <K8S 性能优 ...

  9. Perm 排列计数——Lucas&dfs

    思路:这道题给出的公式看明白后即可得出正解,我们可以把他想象成一颗二叉树,任意一个点的任意一个子孙一直除以2后最终都会到达一终点,终点则为以该点为根的子树的最小值. so--我们可以将根节点作为最后终 ...

  10. 禅道统计BUG解决时长过滤节假日和跨天问题

    之前发过禅道的各种数据统计报表,使用过程中优化了一些,反映最多的是项目bug的解决时长统计问题: 1.比如当天下班左右提交的bug,研发第二天来解决,晚上这段时间应该去掉,不应计算在内 2.节假日.周 ...