是何道理?

良朋 2020-05-20 09:21:44
有点滑稽

string str = "4";
Int16 i = Convert.ToInt16(Convert.ToInt16(str) - 1);
Int16 j = Convert.ToInt16(str) - 1;

因为i和j其它函数要作为short使用, 所以定义成int16,以上语句i赋值行是可以的,j那一行报错,这是何道理?
...全文
773 21 打赏 收藏 转发到动态 举报
AI 作业
写回复
用AI写文章
21 条回复
切换为时间正序
请发表友善的回复…
发表回复
weixin_44615268 2020-05-25
  • 打赏
  • 举报
回复
隐式转换问题,受教了,
luj_1768 2020-05-23
  • 打赏
  • 举报
回复
这个问题是语言规范与语言实现的问题:对于一些不很重要、或者没有什么实际意义的操作,语言实现的解决思路是(你要买半个包子,商家收了你一个包子的钱,并且给了你一个包子!)
闭包客 2020-05-22
  • 打赏
  • 举报
回复
其实减号 - 是一个函数。 当减号函数的左边参数是 short,而右边参数是 int 的时候,函数的返回值是 int 其实等于号 = 也是一个函数。 当等于号函数的左边参数和右边参数的类型不相同的时候,编译器会检查右边参数有没有到左边参数的隐式转换函数,如果没有,编译器,也不知道怎么处理这种问题,所以就报错了。
真相重于对错 2020-05-22
  • 打赏
  • 举报
回复
几乎所有语言,不同类型数据互相运算,都会发生所谓扩位的现象,c++/c就是这样,两种类型的数据相互运算,结果会自动转换为位数比较大的类型,这是符合原理,如果转换为位数小的类型,那么很可能会丢失了数据比如32位与16位运算,如果结果是16位,那么32位的高位部分就会丢失。 那么会不会转换位更大位数的类型,比如16位+32位结果为64位,我觉得这是一种浪费。而且多大算合适?为什么不转位48位?或者64位?
m0_38045792 2020-05-22
  • 打赏
  • 举报
回复
编程小白在线学习一下
Bridge_go 2020-05-21
  • 打赏
  • 举报
回复
int a1 = 4; short b1 = 4; int a2 = b1; short b2 = a1; 试下这个就知道了 前面说错了,是int不能隐式转换为short int范围比short的大,必须显式转换 在IDE里面,整型默认为int,所以Convert.ToInt16("4") - 1 返回的是int类型
wanghui0380 2020-05-21
  • 打赏
  • 举报
回复
聪明的程序员从不会跟规则讲道理,规则不讲道理。编译器不让过,你就把他写过了。 写编译器的人想怎么认为就怎么认为,不同的语言不同的规则,你这纠结了。那要纠结的去了,为啥python让你过,C++让你过,java不让你过,net不让你过,JavaScript又让你过,跟规则讲道理?没道理可讲 喜欢纠结,喜欢矫情的有得说我们神叨,欺负人。 姑且不论编译器不会让你过,就算编译器让你过了,兹要是合格程序员都会写测试的(我不想提什么TDD,但是自己的写的自己不测试,你都过不去自己这关对么)
正怒月神 2020-05-21
  • 打赏
  • 举报
回复
引用 13 楼 良朋 的回复:
[quote=引用 11 楼 正怒月神 的回复:] [quote=引用 9 楼 良朋 的回复:] 我的问题是 Short i=Convert.ToInt16(str) - 1; 报错 而 Short i=Convert.ToInt16(Convert.ToInt16(str) - 1); 不报错 Convert.ToInt16(str) - 1;赋值给i, vs编译器报错, 而把它放在括号中,让它参与运算,编译器就不报错了。 觉得挺没道理的。
因为你在外面强制转换了。Short i=Convert.ToInt16(Convert.ToInt16(str) - 1); [/quote] 说不通的。比如: int m = Convert.ToInt16("4") - 1; //不报错 Int16 n = Convert.ToInt16("4") - 1; //报错 怎么解释? 还有: Int16 a = 3; short b = 3; if (a==b) { int y = a; Int32 x = b; } 以上语句都不报错,又怎样解释? 不追究它了, 调试通就算了。 [/quote] 怎么说不通呢。。。 Convert.ToInt16("4") - 1 默认会转换为int32类型操作。 a==b 这个也是一样的道理。
良朋 2020-05-21
  • 打赏
  • 举报
回复
引用 11 楼 正怒月神 的回复:
[quote=引用 9 楼 良朋 的回复:] 我的问题是 Short i=Convert.ToInt16(str) - 1; 报错 而 Short i=Convert.ToInt16(Convert.ToInt16(str) - 1); 不报错 Convert.ToInt16(str) - 1;赋值给i, vs编译器报错, 而把它放在括号中,让它参与运算,编译器就不报错了。 觉得挺没道理的。
因为你在外面强制转换了。Short i=Convert.ToInt16(Convert.ToInt16(str) - 1); [/quote] 说不通的。比如: int m = Convert.ToInt16("4") - 1; //不报错 Int16 n = Convert.ToInt16("4") - 1; //报错 怎么解释? 还有: Int16 a = 3; short b = 3; if (a==b) { int y = a; Int32 x = b; } 以上语句都不报错,又怎样解释? 不追究它了, 调试通就算了。
良朋 2020-05-21
  • 打赏
  • 举报
回复
引用 10 楼 Bridge_go 的回复:
Convert.ToInt16(str) - 1 得到的是int类型 Convert.ToInt16(Convert.ToInt16(str) - 1) 得到的是short类型 short不能隐式转换为int
你的说法不正确,它们是可以隐式转换的,Int16就是short,我们平常用的int其实是Int32。下面的写法VS是不报错的。 Int16 a = 3; short b = 3; if (a==b) { int y = a; Int32 x = b; }
Min1997Aaaa 2020-05-21
  • 打赏
  • 举报
回复
厉害厉害不愧是大佬
正怒月神 2020-05-20
  • 打赏
  • 举报
回复
我个人认为, 之所以存在将byte,short,ushort等等转换成int32的规范, 应该是考虑溢出的问题。 但是到底转int32还是long,这就仁者见仁了。 不然的话,为什么要默认转int32呢? 按照楼主的问题,其实就是为什么是int32, 那么用语言规范来说明,其实还是没有说出这个问题。为什么语言规范是这么规范的。 当然,溢出也只是我认为,仁者见仁而已。
github_36000833 2020-05-20
  • 打赏
  • 举报
回复
这是C#语言规范,跟是否运算溢出没有直接关系。 int + int也可能溢出,但结果不会自动提升到long。
int i = int.MaxValue;
int i2 = i + i; // -2
github_36000833 2020-05-20
  • 打赏
  • 举报
回复
另一篇文章:
引用 :
二进制数值升级 二元数值升级发生在预定义 +、-、*、/、%、&、|、^、==、!=、>、<、>=和 <= 二元运算符的操作数。 二进制数值升级会隐式地将两个操作数转换为通用类型,在非关系运算符的情况下,也会成为运算的结果类型。 二进制数值升级包括应用下列规则,顺序如下: 如果任一操作数为类型 decimal,则将另一个操作数转换为类型 decimal,如果另一个操作数的类型为 float 或 double,则会发生绑定时错误。 否则,如果其中一个操作数为 double类型,则另一个操作数将转换为类型 double。 否则,如果其中一个操作数为 float类型,则另一个操作数将转换为类型 float。 否则,如果其中一个操作数为 ulong类型,则另一个操作数将转换为类型 ulong,如果另一个操作数的类型为 sbyte、short、int或long,则会发生绑定时错误。 否则,如果其中一个操作数为 long类型,则另一个操作数将转换为类型 long。 否则,如果其中一个操作数的类型为 uint,另一个操作数的类型为 sbyte、short或 int,则这两个操作数都将转换为类型 long。 否则,如果其中一个操作数为 uint类型,则另一个操作数将转换为类型 uint。 否则,两个操作数都将转换为 int类型
见: https://docs.microsoft.com/zh-cn/dotnet/csharp/language-reference/language-specification/expressions#numeric-promotions
正怒月神 2020-05-20
  • 打赏
  • 举报
回复
Int16 j = (short)(Convert.ToInt16(str) - 1);
因为short的任何操作,在编译器看来,都不清楚你是否会溢出。 所以会默认帮你转成int32
github_36000833 2020-05-20
  • 打赏
  • 举报
回复
引用 微软文档:
When operands are of other integral types (sbyte, byte, short, ushort, or char), their values are converted to the int type, which is also the result type of an operation.
翻译为: 当操作数是其他整数类型(sbyte,byte,short,ushort或char)时,它们的值将转换为int类型,这也是操作的结果类型。 见: Arithmetic operators (C# reference) https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/operators/arithmetic-operators
雪狼孤竹 2020-05-20
  • 打赏
  • 举报
回复
运算结果是基于操作数中“大”的类型算的吧。
雪狼孤竹 2020-05-20
  • 打赏
  • 举报
回复
string str = "4"; Int16 i = Convert.ToInt16(Convert.ToInt16(str) - 1); int j = Convert.ToInt16(str)-1; 试了,默认运算结果为int的。
良朋 2020-05-20
  • 打赏
  • 举报
回复
Convert.ToInt16(str) - 1; //报错 Convert.ToInt16(Convert.ToInt16(str) - 1); //不报错
正怒月神 2020-05-20
  • 打赏
  • 举报
回复
引用 9 楼 良朋 的回复:
我的问题是 Short i=Convert.ToInt16(str) - 1; 报错 而 Short i=Convert.ToInt16(Convert.ToInt16(str) - 1); 不报错 Convert.ToInt16(str) - 1;赋值给i, vs编译器报错, 而把它放在括号中,让它参与运算,编译器就不报错了。 觉得挺没道理的。
因为你在外面强制转换了。Short i=Convert.ToInt16(Convert.ToInt16(str) - 1);
加载更多回复(1)

111,094

社区成员

发帖
与我相关
我的任务
社区描述
.NET技术 C#
社区管理员
  • C#
  • AIGC Browser
  • by_封爱
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

让您成为最强悍的C#开发者

试试用AI创作助手写篇文章吧