英文:
C# Inline if statement returns wrong type
问题
I'm creating a Json parser in a single file, while parsing ints and doubles I got an error that a double was returned while I used int.Parse(num)
.
我正在创建一个单文件的Json解析器,在解析整数和浮点数时,出现了一个错误,即在使用 int.Parse(num)
时返回了一个双精度浮点数。
I checked it with this: ((true ? int.Parse(num) : double.Parse(num)).GetType().Name
and this for some reason returns a double even though there shouldn't be a way for it to return that.
我使用以下代码进行了检查:((true ? int.Parse(num) : double.Parse(num)).GetType().Name
,但不知何故,它返回了一个双精度浮点数,尽管不应该返回。
My leading theory is that C# really likes its types, a 1 is valid inside an int and a double, but a 1.1 is only valid in a double so it chooses the double even though the return type is "object".
我目前的主要理论是,C#非常喜欢类型,1在整数和双精度浮点数内都是有效的,但1.1只在双精度浮点数内有效,因此它选择了双精度浮点数,即使返回类型是 "object"。
Example:
function object ParseValue(string num)
{
return true ? int.Parse(num) : double.Parse(num)
}
ParseValue("1").GetType().Name > Double
示例:
function object ParseValue(string num)
{
return true ? int.Parse(num) : double.Parse(num)
}
ParseValue("1").GetType().Name > Double
英文:
I'm creating a Json parser in a single file, while parsing ints and doubles I got an error that a double was returned while I used int.Parse(num)
.
I checked it with this: ((true ? int.Parse(num) : double.Parse(num)).GetType().Name
and this for some reason returns a double even though there shouldn't be a way for it do return that.
My leading theory is that C# really likes it's types, a 1 is valid inside an int and a double, but a 1.1 is only valid in a double so it chooses the double even though the return type is "object".
Example:
function object ParseValue(string num)
{
return true ? int.Parse(num) : double.Parse(num)
}
ParseValue("1").GetType().Name > Double
If you have another possible theory please do share.
答案1
得分: 2
This is the expected and only possible behavior. The ternary operator cannot return two different types from the same expression. Both expressions must either be the same type or one must be assignable to the other. In this case, int
is assignable to double
so it is double
that the expression returns. Try using that operator with two types that are completely incompatible and the compiler will choke on it for that very reason. If you want two different types, then you would have to actually use an if
/else
block.
If you think of the ternary operator as a method - it's not but there are enough similarities for this purpose - then it would look something like this:
T Ternary<T>(bool input, T output1, T output2)
{
if (input)
{
return output1;
}
return output2;
}
If you were to call that method and pass an int
and a double
as arguments, T
would be inferred as double
and the int
would be converted to that type because both outputs have to be the same type, and the alternative might lose data.
英文:
This is the expected and only possible behaviour. The ternary operator cannot return two different types from the same expression. Both expressions must either be the same type or one must be assignable to the other. In this case, int
is assignable to double
so it is double
that the expression returns. Try using that operator with two types that are completely incompatible and the compiler will choke on it for that very reason. If you want two different types then you would have to actually use an if
/else
block.
If you think of the ternary operator as a method - it's not but there enough similarities for this purpose - then it would look something like this:
T Ternary<T>(bool input, T output1, T output2)
{
if (input)
{
return output1;
}
return output2;
}
If you were to call that method and pass an int
and a double
as arguments, T
would be inferred as double
and the int
would be converted to that type, because both outputs have to be the same type and the alternative might lose data.
答案2
得分: 2
三元运算符只能返回一种类型,所以你可以将值强制转换为object
:如果value
可以解析为int
,则返回装箱的int
,否则返回装箱的double
:
private static object ParseValue(string value) =>
int.TryParse(value, out int intValue) ? (object) intValue
: (object) double.Parse(value);
如果你愿意,你可以扩展它以支持更多类型:
private static object ParseValue(string value) =>
bool.TryParse(value, out bool bValue) ? (object) bValue
: int.TryParse(value, out int iValue) ? (object) iValue
: double.TryParse(value, out double dValue) ? (object) dValue
: DateTime.TryParseExact(value,
CultureInfo.CurrentCulture.DateTimeFormat.RFC1123Pattern,
default,
DateTimeStyles.None,
out DateTime dtValue) ? (object)dtValue
: (object) value;
在这里,我们尝试将值解析为bool
、int
、double
、DateTime
(按照此顺序,直到第一个成功),如果所有选项都失败,则返回原始字符串。
英文:
Ternary operator can return one type only, so you can cast values to object
: if value
can be parsed to int
we return boxed int
, otherwise boxed double
:
private static object ParseValue(string value) =>
int.TryParse(value, out int intValue) ? (object) intValue
: (object) double.Parse(value);
You can elaborate it into more types, if you like:
private static object ParseValue(string value) =>
bool.TryParse(value, out bool bValue) ? (object) bValue
: int.TryParse(value, out int iValue) ? (object) iValue
: double.TryParse(value, out double dValue) ? (object) dValue
: DateTime.TryParseExact(value,
CultureInfo.CurrentCulture.DateTimeFormat.RFC1123Pattern,
default,
DateTimeStyles.None,
out DateTime dtValue) ? (object)dtValue
: (object) value;
here we try parse into bool
, int
, double
, DateTime
(in this order up to the first success), and if all options are failed, return original string
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论