Суффикс C # за числовым литералом

Я новичок в C # и хочу понять, как работают значения. Если я посмотрю на обычное целочисленное значение, у него есть 3 важные части: тип, имя и значение.

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 означает "без знака" и позволяет значению быть вдвое большим, чем обычно. Затем вы снова получите суффикс U и букву L, как сказал Google. Насколько я понимаю, «литералы» - это типы значений, содержащие числа. Но я не понимаю, почему этот ulong работает даже без суффикса?

ulong bigOne = 2985825802805280508;

Затем я попробовал что-то другое, чтобы понять важность суффикса

byte testLong = 12312UL;

Это не сработало, потому что значение слишком велико для байта (254), и суффикс не преобразует его в длинную переменную.

Почему для объявления недостаточно первого слова (типа)? Первого слова должно хватить, чтобы определить тип. Лучше всего всегда давать значениям суффикс?


person user3772108    schedule 06.01.2016    source источник
comment
Вы правы, достаточно одного объявления типа, когда есть еще и присваивание. Вот почему в C # было добавлено ключевое слово var: msdn.microsoft.com/en- us / library / bb383973.aspx   -  person Max♦    schedule 06.01.2016
comment
U для беззнакового, а не неназначенного.   -  person Lee Taylor    schedule 06.01.2016
comment
А как насчет вычислений типа 4.0 / 3? Следует использовать одинарную или двойную точность? Это действительно влияет на результат. Или считать 2000000000 * 3? Это переполнение или просто долгое время? Вы не всегда напрямую назначаете ценности.   -  person dryman    schedule 06.01.2016
comment
Это в основном приведение типов во время выполнения, чтобы дать указания компилятору. 1000 - это int, но если вы инициализируете его так долго, вам нужно поставить L в конце. Дополнительную информацию можно найти здесь.   -  person Mihai-Daniel Virna    schedule 06.01.2016
comment
Спасибо за совет, Ли Тейлор, я исправил его.   -  person user3772108    schedule 06.01.2016
comment
Я посмотрю по ссылкам. Спасибо Макс и Михай-Даниэль Вирна.   -  person user3772108    schedule 06.01.2016
comment
Спасибо dryman, но я уже сказал, что хочу double, float, .. в начале объявления, я думаю? Но со ссылкой от Макса это имеет больше смысла. Первое слово - это просто начало объявления, а части, стоящие за знаком =, важны для его типа. Когда я правильно понял?   -  person user3772108    schedule 06.01.2016
comment
@ user3772108 Тот факт, что вы заявили, что создаете переменную типа float, не и не может обязательно определять тип числового литерала, который вы ей назначаете.   -  person Servy    schedule 06.01.2016


Ответы (3)


Вы путаете здесь две разные вещи:

float testFloat = 3.0F;

float сообщает компилятору, что переменная testFloat будет значением с плавающей запятой. F сообщает компилятору, что литерал 3.0 - это float. Компилятору необходимо знать обе части, прежде чем он сможет решить, может ли он назначить литерал переменной без преобразования или с неявным преобразованием.

Например, вы можете сделать это:

float testFloat = 3;

И это нормально. Поскольку компилятор увидит 3 как буквальное целое число, но он знает, что может присвоить это значение с плавающей запятой без потери точности (это неявное преобразование). Но если вы сделаете это:

float testFloat = 3.0;

3.0 является буквальным двойником (потому что это значение по умолчанию без суффикса), и он не может неявно (то есть автоматически) преобразовать двойное значение в число с плавающей запятой, поскольку число с плавающей запятой имеет меньшую точность. Другими словами, информация может быть потеряна. Таким образом, вы либо говорите компилятору, что это буквальное значение с плавающей запятой:

float testFloat = 3.0f;

Или вы можете сказать, что у вас все в порядке с любой потерей точности, используя явное приведение:

float testFloat = (float)3.0;
person Matt Burland    schedule 06.01.2016
comment
Точно. Если вы сделаете var result = 4 / 3;, компилятор должен решить, будет ли это целочисленная операция или операция с плавающей запятой, и это зависит только от того, что находится справа от оператора присваивания. По умолчанию целочисленные значения считаются int, а десятичные значения считаются double. Таким образом, result будет int из 1. Если вместо этого вы сделаете 4 / 3.0, result будет double со значением 1,3333333. - person Andrew; 06.01.2016
comment
Теперь я лучше понимаю спасибо. Я никогда не делал декларации с расчетом в ней. Думал, что точки между числами должно быть достаточно, чтобы компилятор понял. - person user3772108; 06.01.2016
comment
Но даже с расчетным примером. Плавающего в начале должно хватить, чтобы сказать, что я хочу поплавок? Потому что Byte to Long с одним суффиксом не работает? - person user3772108; 06.01.2016
comment
@ user3772108: Нет, это не так. Потому что компилятор должен знать, что такое левая и правая части, прежде чем он сможет решить, действительно ли присвоение. Как и в ответе Серви, он не может определить тип правой части на основе контекста левой части. - person Matt Burland; 06.01.2016

Все выражения 1 должны разрешаться в тип. Таким образом, выражение 42 всегда должно иметь ровно один тип (это бывает int). Это не может быть int, если вы присваиваете его переменной int, и double, если вы присваиваете его double. Контекст, в котором используется выражение, никогда не 1 используется для определения того, в какой тип оно разрешается.

Вот почему числовые литералы могут иметь суффиксы; это способ определения типа этого выражения в этом выражении.

Обратите внимание, что существуют также неявные преобразования между многими числовыми типами, поэтому, если вы пишете double d = 42;, выражение 42 на самом деле является целым числом, но для него выполняется оператор неявного преобразования, который преобразует его в double перед назначением.

1 Здесь есть несколько исключений, таких как лямбда-выражения, для которых тип выражения зависит от того, как оно используется, и группы методов; в вакууме эти выражения не имеют типа.

person Servy    schedule 06.01.2016
comment
Ваш ответ и Мэтт Берланд очень помогли мне понять. Большое спасибо за это. - person user3772108; 06.01.2016

Существует другой способ объявить переменную без указания типа перед именем:

var myNumber = 10;

В этом случае тип переменной будет определяться буквальным значением.

Если вы используете тип (double | float | int | ...) вместо "var", компилятор выполнит преобразование буквального значения в тип переменной (когда это возможно).

Итак, я думаю, что суффикс важен, когда вы используете «var» для объявления переменных, а тип буквального значения не является значением по умолчанию, связанным, когда суффикс не используется;

Есть еще одна причина, по которой суффикс использования слишком полезен, например, в ситуации, когда вы хотите выполнять неявные преобразования в выражениях.

person Gean Ribeiro    schedule 06.01.2016
comment
Это одна из ситуаций, когда необходимость различать разные числовые литералы с помощью суффиксов актуальна, но это не причина, и, конечно, не единственная такая ситуация (в конце концов, var был добавлен в несколько версий в язык, но потребность в суффиксах существовала с самого начала). - person Servy; 06.01.2016
comment
Итак, я могу объявить каждую переменную только с помощью var и правильного суффикса? - person user3772108; 06.01.2016
comment
@ user3772108 В большинстве случаев да, есть некоторые исключения, которые вы не можете, например, определить Func. Но большинство объявлений можно разрешить с помощью var, например: var arrayOfInt = new [] {1,2,3}. Нельзя использовать пример: Func<int,int,int> add = (a,b) => a+b, в этом случае вы должны определить тип переменной. Вы можете узнать больше о var здесь, msdn.microsoft.com/en-us/library /bb383973.aspx - person Alberto Monteiro; 06.01.2016
comment
А если я хочу, чтобы в массиве была десятичная дробь, это было бы var arrayOfInt = new [] {1,2.0M,3}? - person user3772108; 06.01.2016
comment
Спасибо за ссылку, Альберто Монтейро, я посмотрю. - person user3772108; 06.01.2016
comment
@AlbertoMonteiro Нет локальной переменной, которую нельзя объявить с помощью var. В случае лямбда-выражения вам нужно будет изменить правую часть присваивания, но вы всегда можете создать ситуацию, в которой можно использовать var. - person Servy; 06.01.2016
comment
Да, я могу это сделать var func = new Func<int,int,int>((a,b) => a+b). Это другое утверждение действительно Func<int,int,int> add = (a,b) => a+b. Но это утверждение невозможно var func = (a,b) => a+b. Так что есть. - person Alberto Monteiro; 06.01.2016