如果程序希望使用一个值类型实例来进行同步,通常都会是错误(bug)。但运行时应该认为这是非法并抛出异常吗?在下面的代码示例中如果两个不同的线程同时调用同一个Counter 实例的Increment 方法,将会发生什么?

class Counter{private int _i;public int Increment(){lock (_i){return ++_i;}}}

当我们打算这样做的时候,会发现这样一个意想不到的问题:C#编译器不允许lock关键字使值类型。不过,我们已经熟知lock关键字的内部原理,可以变通一下:

class Counter{private int _i;public int Increment(){bool acquired = false;try{Monitor.Enter(_i, ref acquired);return ++_i;}finally{if (acquired) Monitor.Exit(_i);}}}

这样一来,程序就引入了一个错误(bug)。多个线程能够同时进入锁内修改_i,而且调 Monitor.Exit还会抛出异常.Monitor.Enter 方法接收的是System.Object类型的参数,是一个引用,而我们传递的是值类型(按值传递)。尽管此时(在需要引用的地方传递值),我们所传递的值并没有被更改,但是传递给 Monitor.Enter 方法的值与传递给Monitor.Exit方法的值具有不同的标识。类似地,在一个线程里传递给Monitor.Enter方法的值,与另一个线程里传递给Monitor.Enter的值也具有不同的标识。如果我们在需要引用的地方(按值)传递值,就不能获得正确的锁语义。

当方法返回引用类型时,如果我们返回了一个值类型,在语义上也不是非常合适。例如,下面的代码:

object GetInt()
{
int i = 42;return i; }
object obj= GetInt();

GetInt方法按值返回一个值类型,然而调用者期望方法返回的是引用类型。方法本可以返回在方法执行时存储i的栈位置,但得到的将是到无效内存地址的引用,因为方法的栈帧会在方法返回前清空。这说明默认情况下按值复制的值类型语义,并不适合需要对象引用(指向托管堆)的地方。

技术群:添加小编微信并备注进群

小编微信:mm1552923

公众号:dotNet编程大全

C# 值类型的局限性相关推荐

  1. python参数类型限定_python限定方法参数类型、返回值类型、变量类型等|python3教程|python入门|python教程...

    https://www.xin3721.com/eschool/python.html typing模块的作用 自python3.5开始,PEP484为python引入了类型注解(type hints ...

  2. Swift 值类型和引用类型的内存管理

    1.内存分配 1.1 值类型的内存分配 在 Swift 中定长的值类型都是保存在栈上的,操作时不会涉及堆上的内存.变长的值类型(字符串.集合类型是可变长度的值类型)会分配堆内存. 这相当于一个 &qu ...

  3. C# 值类型与引用类型

    值类型在栈中分配内存空间并保存数据: 引用类型在堆上分配内存空间并保存数据,且在栈中保存指向堆中的数据地址: 值类型变量声明后,不管是否已经赋值,编译器为其分配内存. 引用类型当声明一个类时,只在栈中 ...

  4. C# 引用类型和值类型

    1.引用类型 FCL(Framework)中的大多数类型都是引用类型,引用类型总是在托管堆中分配的,C#的new操作符会返回对象的内存地址,也就是指对象数据的内存地址.在使用引用类型时,存在以下性能问 ...

  5. 述说C#中的值类型和引用类型的千丝万缕

    关于值类型和引用类型方面的博客和文章可以说是汗牛充栋了,今天无意中又复读了一下这方面的知识,感觉还是有许多新感悟的,就此时间分享一下: CLR支持两种类型:值类型和引用类型,看起来FCL的大多数类型是 ...

  6. Redis键命令(查找键、判断键值是否存在、查看键值类型、删除键值、设置过期时间、查看键值有效时间)

    [键命令对于不同数据结构类型通用] 查找键,参数⽀持正则表达式 keys pattern 例2:查看名称中包含a的键 keys a* 判断键是否存在,如果存在返回1,不存在返回0 exists key ...

  7. Java值类型与引用类型的不同

    [定义] 引用类型表示你操作的数据是同一个,也就是说当你传一个参数给另一个方法时,你在另一个方法中改变这个变量的值,那么调用这个方法是传入的变量的值也将改变. 值类型表示复制一个当前变量传给方法,当你 ...

  8. php引用类型变量,PHP变量的值类型和引用类型

    PHP 变量在内存中保存的并不直接是值的内容而是值的地址.比如: $a = 1; 从表面上看起来似乎是 $a 直接存储了 1 这个值.但是实际情况是,PHP 解释器创建了变量 $a , 将值 1 存入 ...

  9. java 返回值判断_在Java中判断方法重载的条件除了参数外,还可以通过返回值类型判断。_学小易找答案...

    [单选题]若int x;且有下面的程序片断,则输出结果是() . for (x=3; x<6; x++) { printf((x%2) ? "##%d" : "** ...

最新文章

  1. pythonbool运算教学_python,_pandas Series bool与运算,python - phpStudy
  2. get 和 post
  3. multiple Rational objects
  4. RedHat.Enterprise.Linux.5.2 Yum源配置
  5. Qt窗口屏幕居中显示 (ZT)
  6. python爬虫之urllib,伪装,超时设置,异常处理
  7. slf4j日志的最优使用方式
  8. 盘点机器学习领域的五大流派
  9. 标准正态分布的积分怎么求?
  10. 转liunx 常用命令
  11. linux mysql 编译后的版本_LINUX下编译安装最新版本mysql_MySQL
  12. 大叔手记(2):为每个应用程序池单独设置aspnet.config配置文件
  13. HTML+css网站设计布局模板
  14. C盘数据丢失恢复详解和注意事项
  15. 一个比较土但凑合能用的画心方法
  16. 大数据入门级介绍(一)
  17. 共识算法(BABE+GRANDPA)
  18. 为什么可积不一定可导_极限存在、连续、有界、可积、可导/可微之间的关系...
  19. 卷积滤波 英文_图形学之卷积滤波器
  20. Python 多线程、利用request使用代理、利用递归深度抓取电影网页的内容并将电影的介绍和下载链接保存到mysql中

热门文章

  1. (10) 需求征集 -- 权限管理
  2. RHEL5.3下MRTG+SNMP的搭建
  3. 参数方程求二阶偏导_偏微分方程
  4. UBUNTU 用户及用户组管理 修改用户和主机名
  5. JAVA多线程之先行发生原则
  6. angularjs的ng-repeat回调
  7. AIX 环境下遇到Device Busy问题
  8. 【转】sqlserver游标概念与实例全面解说
  9. 转.h和.cpp文件的区别
  10. NHibernate学习笔记(二):one-to-one关系映射