为什么TypedReference在幕后

我发现的其他用途TypedReference:

C#中的“专门化”泛型(这是类型安全的):

static void foo<T>(ref T value)
{//This is the ONLY way to treat value as int, without boxing/unboxing objectsif (value is int){ __refvalue(__makeref(value), int) = 1; }else { value = default(T); }
}

误用时不安全,但正确使用时快速和安全:

//This bypasses the restriction that you can't have a pointer to T,
//letting you write very high-performance generic code.
//It's dangerous if you don't know what you're doing, but very worth if you do.
static T Read<T>(IntPtr address)
{var obj = default(T);var tr = __makeref(obj);//This is equivalent to shooting yourself in the foot//but it's the only high-perf solution in some cases//it sets the first field of the TypedReference (which is a pointer)//to the address you give it, then it dereferences the value.//Better be 10000% sure that your type T is unmanaged/blittable...unsafe { *(IntPtr*)(&tr) = address; }return __refvalue(tr, T);
}

写一个方法的版本sizeof指令,有时会有用:

static class ArrayOfTwoElements<T> { static readonly Value = new T[2]; }static uint SizeOf<T>()
{unsafe {TypedReferenceelem1 = __makeref(ArrayOfTwoElements<T>.Value[0] ),elem2 = __makeref(ArrayOfTwoElements<T>.Value[1] );unsafe{ return (uint)((byte*)*(IntPtr*)(&elem2) - (byte*)*(IntPtr*)(&elem1)); }}
}

编写一个传递“state”参数的方法,以避免装箱:

static void call(Action<int, TypedReference> action, TypedReference state)
{//Note: I could've said "object" instead of "TypedReference",//but if I had, then the user would've had to box any value typestry{action(0, state);}finally { /*Do any cleanup needed*/ }
}

那么,为什么像这样的使用“不鼓励”(由于缺乏文档)?有什么特别的安全原因吗?如果它不与指针混合(无论如何都不是安全的或可验证的),那么它似乎是完全安全和可验证的。

最新情况:

示例代码来证明,确实,TypedReference可以是两倍的速度(或更多):

using System;
using System.Collections.Generic;
static class Program
{static void Set1<T>(T[] a, int i, int v){ __refvalue(__makeref(a[i]), int) = v; }static void Set2<T>(T[] a, int i, int v){ a[i] = (T)(object)v; }static void Main(string[] args){var root = new List<object>();var rand = new Random();for (int i = 0; i < 1024; i++){ root.Add(new byte[rand.Next(1024 * 64)]); }//The above code is to put just a bit of pressure on the GCvar arr = new int[5];int start;const int COUNT = 40000000;start = Environment.TickCount;for (int i = 0; i < COUNT; i++){ Set1(arr, 0, i); }Console.WriteLine("Using TypedReference:  {0} ticks",Environment.TickCount - start);start = Environment.TickCount;for (int i = 0; i < COUNT; i++){ Set2(arr, 0, i); }Console.WriteLine("Using boxing/unboxing: {0} ticks",Environment.TickCount - start);//Output Using TypedReference:  156 ticks//Output Using boxing/unboxing: 484 ticks}
}

 

用户回答回答于 2018-03-28

__arglist__makeref,和__refvalue语言扩展在C#语言规范中是没有文档的,这些构造用于在引擎盖下实现它们(vararg电话会议,TypedReference类型,arglistrefanytypemkanyref,和refanyva

在VarargLibrary中定义它可以很清楚地表明,它们主要是为了支持可变长度的参数列表,而不是其他的。变量参数列表在不需要与使用varargs的外部C代码接口的平台上没有什么用处。因此,Varargs库不是任何CLI配置文件的一部分。合法的CLI实现可能选择不支持Varargs库,因为它不包含在CLI内核配置文件中:

4.1.6 Vararg 大vararg特征集支持可变长度的参数列表和运行时类型的指针。undefined如果省略:对象引用方法的任何尝试。vararg调用约定或与vararg方法关联的签名编码(请参阅PartitionII)将引发System.NotImplementedException例外。方法使用CIL指令。arglistrefanytypemkrefany,和refanyval将抛出System.NotImplementedException例外。未指定异常的确切时间。类型System.TypedReference不需要定义。

最新情况(回复)GetValueDirect评论):

FieldInfo.GetValueDirectFieldInfo.SetValueDirect基类库的一部分。请注意,.NET Framework类库与基类库之间存在差异。BCL是CLI/C#的一致性实现所需的唯一条件。

一旦使用bcl之外的方法,就会放弃一些可移植性(随着Silverlight和MonoTouch等非.NET CLI实现的出现,这一点变得越来越重要)。即使实现想要增强与Microsoft.NET框架类库的兼容性,它也可以简单地提供GetValueDirectSetValueDirect带着...TypedReference不做TypedReference由运行时特别处理(基本上,使它们与它们的object没有性能效益的对应方)。

如果他们把它记录在C#中,它至少会有几个暗示:

  1. 就像任何一个特征,它五月成为新特性的障碍,特别是因为这个特性并不适合C#的设计,并且需要奇怪的语法扩展和运行时对类型的特殊处理。
  2. C#的所有实现都必须以某种方式实现这个特性,对于不运行在CLI之上或在没有Varargs的CLI之上运行的C#实现来说,这不一定是简单的/可能的。

 

用户回答回答于 2018-03-28

实际上,诸如指针这样的特性,stackalloc,并且在某些情况下存在某些优化的框架函数以提高性能。

我会说初等类型安全的好处,也提高性能类似于Typedeference通过避免拳击和取消拳击。

static void call(Action<int, TypedReference> action, TypedReference state){action(0, state);
}

对此:

static void call<T>(Action<int, T> action, T state){action(0, state);
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/438320.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

C# 中的可变参数方法(VarArgs)

首先需要明确一点&#xff1a;这里提到的可变参数方法&#xff0c;指的是具有 CallingConventions.VarArgs 调用约定的方法&#xff0c;而不是包含 params 参数的方法。可以通过MethodBase.CallingConvention 属性来获取某个方法的调用约定。 举个常见的例子来说&#xff0c;C…

Spring Boot Actuator监控关闭

可以使用如下属性:management.endpoints.enabled-by-defaultfalse * 在YAML中有特殊的含义&#xff0c;所以如果想使用include或者exclude包含所有的端点时要加上引号&#xff0c;如下示例&#xff1a; # 暴露监控端点 management:endpoints:enabled-by-default: false #关闭…

Javascript获取类名方法

函数&#xff1a; entity.getClassName function(obj) { if (obj && obj.constructor && obj.constructor.toString()) { if(obj.constructor.name) { return obj.constructor.name; } let str…

mysql把一个数据库中的数据复制到另一个数据库中的表 2个表结构相同

1。表结构相同的表&#xff0c;且在同一数据库&#xff08;如&#xff0c;table1,table2) Sql &#xff1a;insert into table1 select * from table2 (完全复制) insert into table1 select distinct * from table2(不复制重复纪录&#xff09; insert into table1 select …

!Spring Aop中四个重要概念,切点,切面,连接点,通知

一、基本概念 1. 通知&#xff1a; 就是我们编写的希望Aop时额外执行的那个方法。我们通过Aop希望我们编写的方法在目标方法执行前执行&#xff0c;或者执行后执行。 2. 切点&#xff1a;切点就是我们配置的满足我们条件的目标方法。比如我们规定&#xff1a;名字前面是select…

Spring AOP(通知、连接点、切点、切面)

一、AOP术语 通知&#xff08;Advice&#xff09;   切面的工作被称为通知。通知定义了切面是什么以及何时使用。除了描述切面要完成的工作&#xff0c;通知还解决了何时执行这个工作的问题。 5种通知类型&#xff1a;前置通知&#xff08;Before&#xff09;&#xff1a;在…

Map集合根据key,value排序

/*** 根据map的key排序* * param map 待排序的map* param isDesc 是否降序&#xff0c;true&#xff1a;降序&#xff0c;false&#xff1a;升序* return 排序好的map*/public static <K extends Comparable<? super K>, V> Map<K, V> sortByKey(Map<K, …

C#中几种常用的集合的用法

集合:将一推数据类型相同的数据放入到一个容器内&#xff0c;该容器就是数组&#xff1a;内存中开辟的一连串空间。 非泛型集合 ArrayList集合&#xff1a; ArrayList是基于数组实现的&#xff0c;是一个动态数组&#xff0c;其容量能自动 增长 ArrayList的命名空间System.…

oracle新增,删除字段,设置默认值

增加字段 alter table 表 Add 字段 varchar2(128); 设置字段默认值为时间戳 alter table 表 modify 字段 default sysdata; 删除字段 alter table 表 drop column 字段;

C#使用Redis的基本操作

一&#xff0c;引入dll 1.ServiceStack.Common.dll 2.ServiceStack.Interfaces.dll 3.ServiceStack.Redis.dll 4.ServiceStack.Text.dll 二&#xff0c;修改配置文件 在你的配置文件中加入如下的代码&#xff1a; <appSettings><add key"RedisPath" value…

Navicat将mysql表结构导成oracle表结构

1&#xff0c;选中对应的表右键逆向表到模型 2.点击右上角文件转换模型为 3.模型选择物理&#xff0c;数据库oracle&#xff0c;选择对应的版本 4.新弹出的模型点击右上角文件&#xff0c;导出sql 5.选择路径导出sql

程序员们的三高:高并发、高性能、高可用

你们知道淘宝&#xff0c;京东这些购物商场吗&#xff1f;他们到了双11&#xff0c;双12为什么能支持全国14亿人口同时购物下单呢&#xff0c;因为他们的程序做到了高并发、高性能、高可用。那么你对程序员的三高了解多少呢&#xff1f; 高并发 一. 高并发 高并发是现在互联…

C#接口归纳总结实例详解

本篇文章通过实例代码对接口做了详解&#xff0c;需要的朋友可以参考下 C#接口的学习&#xff0c;在编程中&#xff0c;我们经常会用到接口&#xff0c;那什么是接口呢&#xff1f; 接口描述的是可属于任何类或结构的一组相关功能&#xff0c;所以实现接口的类或结构必须实现…

char 和 varchar 的区别,数据库索引B+树

char 和 varchar 的区别 char(n) &#xff1a;固定长度&#xff0c;效率高&#xff1b;缺点&#xff1a;占用空间&#xff1b;存储固定长度的&#xff0c;使用 char 非常合适。 varchar(n) &#xff1a;可变长度&#xff0c;存储的值是每个值占用的字节再加上一个用来记录其长…

日常收集C#接口知识(知识全面)

本文分为七章节给大家介绍c#接口知识&#xff0c;内容比较详细&#xff0c;特此分享脚本之家平台&#xff0c;供大家参考 第一节 接口慨述 接口&#xff08;interface&#xff09;用来定义一种程序的协定。实现接口的类或者结构要与接口的定义严格一致。有了这个协定&#xff…

mysql按照中文首字母拼音排序

order by convert(排序字段 using gbk)

C#基础操作符详解

本节内容&#xff1a; 1.操作符概览&#xff1b; 2.操作符的本质&#xff1b; 3.操作符与运算顺序 4.操作符详解。 1.操作符概览&#xff1a; 操作符&#xff08;Operator&#xff09;也译为”运算符” 操作符是用来操作数据的&#xff0c;被操作符操作的数据称为操作数&a…

查询sql语句是否使用索引

使用 Explain 命令来查看语句的执行计划 例&#xff1a;Explain select * from table 除过select&#xff0c;其他比如insert&#xff0c;update和delete均可以使用explain查看执行计划 概要描述&#xff1a; id:选择标识符 select_type:表示查询的类型。 table:输出结果集的…

C# 有什么惊艳到你的地方?

作者&#xff1a;皮皮关 链接&#xff1a;https://www.zhihu.com/question/335137780/answer/786853293 来源&#xff1a;知乎 著作权归作者所有。商业转载请联系作者获得授权&#xff0c;非商业转载请注明出处。 很多游戏开发者都是由于Unity而“被迫”使用C#的。但用过一段…

Redis使用场景

缓存&#xff1a;减轻查询压力&#xff0c;提升系统性能&#xff1b; 排行榜&#xff1a;利用 Redis 的 SortSet&#xff08;有序集合&#xff09;实现&#xff1b; 计数器/限速器&#xff1a;利用 Redis 中原子性的自增操作&#xff0c;我们可以统计类似用户点赞数、用户访问…