Resharper Trap "Конвертировать в оператор" return " - PullRequest
6 голосов
/ 09 марта 2009

С учетом следующей процедуры:

private static object ParseNumber(string token, FieldDefinition def)
{
  if (def.Fraction > 0)
    return Double.Parse(token);
  else
    return Int64.Parse(token);
}

Resharper предлагает мне возможность преобразовать его в оператор с троичным оператором:

private static object ParseNumber(string token, FieldDefinition def)
{
  return def.Fraction > 0 ? Double.Parse(token) : Int64.Parse(token);
}

Кто может обнаружить ловушку?

1 Ответ

11 голосов
/ 09 марта 2009

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

На всякий случай, если этого недостаточно, давайте изменим все операторы return так, чтобы они просто возвращали переменную. Вот оригинальный код:

private static object ParseNumber(string token, FieldDefinition def)
{
  if (def.Fraction > 0)
    return Double.Parse(token);
  else
    return Int64.Parse(token);
}

Преобразуйте это соответствующим образом:

private static object ParseNumber(string token, FieldDefinition def)
{
  if (def.Fraction > 0)
  {
    double d = Double.Parse(token);
    object boxed = d; // Result is a boxed Double
    return boxed;
  }
  else
  {
    long l = Int64.Parse(token);
    object boxed = l; // Result is a boxed Int64
    return boxed;
  }
}

А теперь давайте сделаем то же самое с версией с условным оператором:

private static object ParseNumber(string token, FieldDefinition def)
{
  return def.Fraction > 0 ? Double.Parse(token) : Int64.Parse(token);
}

становится

private static object ParseNumber(string token, FieldDefinition def)
{
  // The Int64.Parse branch will implicitly convert to Double
  double d = def.Fraction > 0 ? Double.Parse(token) : Int64.Parse(token);
  object boxed = d; // *Always* a Double
  return boxed;
}

РЕДАКТИРОВАТЬ: По запросу, немного больше информации. Тип условного выражения вида

X ? Y : Z

зависит от типов Y и Z, которые я назову TY и TZ. Есть несколько вариантов:

  • TY и TZ относятся к одному типу: в результате получается тип
  • Существует неявное преобразование из TY в TZ, но не из TZ в TY: результат имеет тип TZ, и преобразование используется, если используется первая ветвь.
  • Существует неявное преобразование из TZ в TY, но не из TY в TZ: результат имеет тип TY, и преобразование используется, если используется вторая ветвь.
  • Существует неявное преобразование в обоих направлениях: ошибка времени компиляции
  • Нет ни одного преобразования: ошибка времени компиляции

Это помогает?

...