Почему var разрешается как Double, а не Long? - PullRequest
4 голосов
/ 14 февраля 2012

В следующем коде я ожидал бы, что var будет преобразован в Int64, но он будет преобразован в double. Почему это так?

string a =  "1234";
bool asInt = true;
var b = (asInt) ? Int64.Parse(a) : Double.Parse(a) ;
Console.WriteLine(b.GetType());

Ответы [ 6 ]

12 голосов
/ 14 февраля 2012

Существует неявное преобразование из Int64 в Double, но не в другую сторону (из-за возможной потери точности в этом направлении).

Поскольку обе «ветви» условной необходимости необходимо разрешитьк тому же типу тип b заканчивается как Double.

5 голосов
/ 14 февраля 2012

Вы можете неявно привести long к double.

Вы не можете неявно привести double к long

Так что компилятор C # определил единственную возможностьтип вашей переменной был double.

См. Таблица неявных числовых преобразований .

4 голосов
/ 14 февраля 2012

Поскольку компилятор должен выводить тип, который может содержать значения как Int64.Parse(a), так и Double.Parse(a), не требуя явного приведения. Если вывести long, точность будет потеряна в другом выражении.

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

if (asInt)
{
    var b = Int64.Parse(a); // will infer a `long`
    Console.WriteLine(b.GetType());
}
else
{
    var b = Double.Parse(a); // will infer a `double`
    Console.WriteLine(b.GetType());
}
1 голос
/ 14 февраля 2012

Компилятор C # выводит тип из общего знаменателя между двумя возвращаемыми типами вашей троичной переменной. Int64 может быть неявно преобразован в Double. Обратное не так.

Обратите внимание, что состояние Boolean в вашем примере кода не имеет ничего общего с предполагаемым типом.

0 голосов
/ 14 февраля 2012

Я удивлен, что никто не указал, что , если вы знаете, что это будет допустимое значение long , вы можете изменить поведение компилятора с явным приведением и просто использовать long.

Это может быть или не быть полезным, в зависимости от условия, которое определяет значение для asInt, и от того, что вы намереваетесь делать с результатом выражения.Вот пример:

string a =  "1234.56"; 
bool asDouble = a.Contains("."); 
var b = asDouble ? (long)Double.Parse(a) : Int64.Parse(a);
Console.WriteLine(b.GetType());

На самом деле, в этом примере вам не нужен условный оператор;это тоже сработало бы:

string a =  "1234.56"; 
var b = (long)Double.Parse(a);
Console.WriteLine(b.GetType());

Другими словами, возможно, что лучшее решение не будет использовать троичный оператор, но вопрос не дает достаточного контекста, чтобы знать.

0 голосов
/ 14 февраля 2012

Это работа оператора ?:. Следует привести все результаты к одному типу.

P.S. Подобное поведение + оператора вы знаете:

string a =  "1234";
var b = Int64.Parse(a) + Double.Parse(a) ;
Console.WriteLine(b.GetType());

P.P.S. Чтобы иметь то, что вы хотите, вы должны использовать object:

string a =  "1234";
bool asInt = true;
object b;
if(asInt) b=Int64.Parse(a); else b=Double.Parse(a);
Console.WriteLine(b.GetType());

P.P.P.S. Другой вариант:

        string a = "1234";
#if asInt
        Int64 b = Int64.Parse(a);
#else
        Double b = Double.Parse(a);
#endif
        Console.WriteLine(b.GetType());

для определения asInt использовать

#define asInt
...