数字文字后面的C#后缀

数字文字后面的C#后缀,c#,declaration,literals,variable-declaration,C#,Declaration,Literals,Variable Declaration,我是C#的新手,想了解价值观是如何运作的。如果我看一个普通整数值,它有三个重要部分:类型、名称和值 int testInt = 3; | | | Type Name Value 但是当我看到一个浮点值时,由于后缀F,我有点困惑 float testFloat = 3.0F; | | | | Type Name Value Type 现在它有两种类型,如果没有F后缀,值将是双精度的。但是当我可以用 double testDouble

我是C#的新手,想了解价值观是如何运作的。如果我看一个普通整数值,它有三个重要部分:类型、名称和值

int testInt = 3;
 |    |       |
Type Name   Value
但是当我看到一个浮点值时,由于后缀
F
,我有点困惑

float testFloat = 3.0F;
  |      |        |  |
 Type   Name  Value Type
现在它有两种类型,如果没有
F
后缀,值将是双精度的。但是当我可以用

double testDouble = 3.0D;
第一个单词的
double
就足够了,不是吗?后缀为M的十进制值也是如此:

decimal testDecimal = 3.0M;
然后,当涉及到其他后缀时,我开始感到困惑:

ulong bigOne = 2985825802805280508UL;
我以前在一次测试中使用了
ulong
,知道
u
表示“unsigned”,并使值为正常值的两倍。然后你又得到了U作为后缀,L作为文字,正如谷歌所说。据我理解,“文字”是包含数字的值类型。但我不明白的是,为什么这个ulong即使没有后缀也能工作

ulong bigOne = 2985825802805280508;
然后我尝试了一些不同的方法来理解后缀的重要性

byte testLong = 12312UL;
这不起作用,因为该值对于字节(254)太高,且后缀未将其转换为长变量


为什么第一个单词(类型)不足以声明?第一个单词应该足以说明类型。始终为值指定后缀是最佳做法吗?

存在另一种方法来声明变量,而不在名称前指定类型:

var myNumber = 10;
在这种情况下,变量类型将由文本值定义

如果您使用类型(double | float | int |…)而不是“var”,编译器会将文本值转换为变量类型(如果可能)

因此,我认为当您使用“var”声明变量时,后缀很重要,并且当不使用后缀时,文本值类型不是默认的关联类型


使用后缀太有用还有另一个原因,比如在表达式中进行隐式转换的情况下。

这里您混淆了两种不同的东西:

float testFloat = 3.0F;
float
告诉编译器变量
testFloat
将是一个浮点值。
F
告诉编译器,literal
3.0
是一个
float
。编译器需要知道这两个部分,然后才能决定是否可以在不进行转换或隐式转换的情况下将文本分配给变量

例如,您可以执行以下操作:

float testFloat = 3;
没关系。因为编译器将
3
视为一个文字整数,但它知道它可以将其分配给浮点,而不会丢失精度(这是隐式转换)。但如果你这样做:

float testFloat = 3.0;
3.0
是一个文本双精度(因为这是没有后缀的默认值),它不能隐式(即自动)将双精度转换为浮点,因为浮点精度较低。换句话说,信息可能会丢失。因此,您可以告诉编译器它是一个文本浮点:

float testFloat = 3.0f;
或者你告诉它,你可以通过使用显式强制转换来处理任何精度损失:

所有1表达式都需要可解析为一个类型。因此表达式
42
总是需要有一种类型(它恰好是
int
)。如果将它分配给
int
变量,则它不能是
int
;如果将它分配给
double
,则它不能是
double
。表达式使用的上下文不用于确定其解析为什么类型

这就是为什么数字文字可以有后缀;这是一种在表达式中定义表达式类型的方法

请注意,许多数字类型之间也存在隐式转换,因此如果您编写
double d=42
表达式
42
实际上是一个整数,但在赋值之前,对其执行隐式转换运算符,将其转换为
double


1这里有一些例外,例如lambdas,表达式的类型取决于其使用方式和方法组;在真空中,这些表达式没有类型。

没错,如果还有赋值,一个类型声明就足够了。这就是为什么在C#中添加var关键字:
U
用于未签名,而不是未赋值。还有4.0/3之类的计算呢?它应该使用单精度还是双精度?这确实影响了结果。或者考虑2000000000×3?是溢油还是长油?您并不总是直接指定值。这些基本上是运行时强制转换,用于向编译器提供方向。1000是一个整数,但是如果你初始化它,你需要在它的末尾加一个L。您可以找到更多信息。@user3772108您声明正在创建一个类型为
float
的变量,这一事实并不一定确定您分配给它的数值文本的类型,也不一定能够确定它的类型。如果您执行
var结果=4/3,编译器必须决定它是整数还是浮点运算,这只取决于赋值运算符右侧的内容。默认情况下,整数值被视为
int
,十进制值被视为
double
。因此,这将使
结果
int
为1。如果您改为
4/3.0
结果将是
双精度的
,值为1.3333333。现在我能更好地理解了,谢谢。我从来没有做过有计算的声明。我认为数字之间的点必须足够让编译器理解。但即使是计算示例。开头的浮动应该足以告诉我想要浮动?因为只有后缀的字节变长不起作用?@user3772108:不,不起作用。因为编译器需要知道左边和右边是什么,然后才能决定赋值是否有效。正如Servy的回答一样,它无法决定右侧ba的类型
float testFloat = (float)3.0;