C#内联if语句返回错误类型。

huangapple go评论64阅读模式
英文:

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&lt;T&gt;(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;

在这里,我们尝试将值解析为boolintdoubleDateTime(按照此顺序,直到第一个成功),如果所有选项都失败,则返回原始字符串。

英文:

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) =&gt; 
    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) =&gt; 
    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

huangapple
  • 本文由 发表于 2023年5月7日 21:01:25
  • 转载请务必保留本文链接:https://go.coder-hub.com/76194098.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定