Есть проблемы с объявлением переменной и использованием TryParse для ее инициализации в той же строке? - PullRequest
17 голосов
/ 30 декабря 2010

Этот пример написан на C #, но я ожидаю, что он может применяться к другим так же легко.

Недавно я обнаружил, что следующее, кажется, работает просто отлично:

int i = Int32.TryParse(SomeString, out i) ? i : -1;

Почему-то это выглядитхотя технически переменная i не должна быть доступна в том месте, где она появляется в TryParse.Или я был бы прав, предполагая, что int i фактически объявляет переменную, даже если еще нет конца оператора?

Ответы [ 3 ]

10 голосов
/ 30 декабря 2010

int i объявляет переменную, и использование ее в параметре out инициализирует ее. Поскольку предикат должен быть оценен до последующего, поэтому i объявляется и инициализируется перед использованием. (out параметры должны быть назначены перед возвратом, поэтому он обязательно инициализируется в любом случае.)

Тем не менее, есть мои коллеги, которые не могли бы увидеть что-то подобное на почве стиля. : -)

РЕДАКТИРОВАТЬ: После изучения того, как это вытряхнуло, я предложу несколько возможных альтернативных вспомогательных методов. Именование статического класса здесь действует как документация намерений для вспомогательных методов.

internal static class TryConvert
{
    /// <summary>
    /// Returns the integer result of parsing a string, or null.
    /// </summary>
    internal static int? ToNullableInt32(string toParse)
    {
        int result;
        if (Int32.TryParse(toParse, out result)) return result;
        return null;
    }

    /// <summary>
    /// Returns the integer result of parsing a string,
    /// or the supplied failure value if the parse fails.
    /// </summary>
    internal static int ToInt32(string toParse, int toReturnOnFailure)
    {
        // The nullable-result method sets up for a coalesce operator.
        return ToNullableInt32(toParse) ?? toReturnOnFailure;
    }
}

internal static class CallingCode
{
    internal static void Example(string someString)
    {
        // Name your poison. :-)
        int i = TryConvert.ToInt32(someString, -1);
        int j = TryConvert.ToNullableInt32(someString) ?? -1;

        // This avoids the issue of a sentinel value.
        int? k = TryConvert.ToNullableInt32(someString);
        if (k.HasValue)
        {
            // do something
        }
    }
}
4 голосов
/ 31 декабря 2010

Помните, что в CIL нет троичного оператора.

int i = Int32.TryParse(SomeString, out i) ? i : -1;

Ваш код преобразуется в CIL, представляющий следующий код C #:

int i;
if (Int32.TryParse(SomeString, out i))
  i = i;
else
  i = -1;

Что отлично.

4 голосов
/ 31 декабря 2010

Я недавно обнаружил, что следующее, кажется, работает просто отлично

 int i = Int32.TryParse(SomeString, out i) ? i : -1;

Это работает, но это не хорошо.

Есть ли проблемы с объявлением переменной и использованием TryParse для ее инициализации в той же строке?

Да, удобочитаемость. Я думаю, что это выглядит ужасно, и это делает двойную работу.


Часть вашей проблемы в том, что вы хотите -1 в качестве значения по умолчанию. Int32.TryParse явно определяет 0 как выходное значение при сбое преобразования.

Я бы все равно разбил его на 2 строки для удобства чтения.

int i;
if (! int.TryParse(SomeString, out i))  i = -1;

А когда вам это нужно, напишите вспомогательный метод (статический, но не с расширением):

int i = Utils.ParseInt(SomeString, -1);
...