2015-04-10 3 views
1

Мне нужно изменить «выход» на «возврат», потому что было бы удобнее в использовании, но я действительно не знаю, как преобразовать эти функции, чтобы использовать «return» not «out ». У меня есть открытый класс и в этом классе у меня есть метод BOOLИзмените параметр для возвращаемого значения

public static bool GetParameter(this Dictionary<string, string> context, string parameterName, out int parameter) 
    { 
     string stringParameter; 
     context.TryGetValue(parameterName, out stringParameter); 
     return int.TryParse(stringParameter, out parameter); 
    } 

и я использую эту функцию так:

private int _personID; 
    public void SomeFunction() 
    { 
     _classInstance.Context.GetParameter("PersonID", out _personID); 
    } 

Спасибо!

+0

что вы пытаетесь вернуться, только целое число? делает ли результат «TryParse»? – Sayse

+0

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

+0

Что бы вы вернули, если 'context' не содержит ключ' parameterName', или если значение для этого ключа не представляет допустимое целое число? – Corak

ответ

3

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

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

  • когда асинхронные вызовы участвуют. Тестирование того, существует ли что-то в базе данных, например, и возвращает ее, если это так, не работает с параметром out.
  • , когда вы что-то делаете свободно, например, в LINQ.

Кроме того, это прекрасная модель для использования, которая передает много информации, не жертвуя целостностью данных (или делая какие-либо предположения о том, что вы ожидаете).

Проблема здесь, и причина, по которой вы возвращаете bool, как она есть сейчас, обрабатывает ошибки. Итак, вам нужно найти альтернативный способ обращения с ними.

Выбор здесь действительно зависит от того, какой вход вы ожидаете.

Используйте исключение:

Самый простой, наверное, просто не обращаться с ними. Пусть они распространяются. Если что-то не найдено или не разбирается, просто выбросьте исключение.

Использование исключений для направления регулярного потока приложений обычно считается плохой практикой, но может быть использовано для интерпретации того, что такое «обычный поток приложений». Поэтому обязательно посмотрите на свои данные и обстоятельства.

public static int GetParameter(this Dictionary<string, string> context, string parameterName) 
{ 
    string stringParameter = context[parameterName]; 
    return int.Parse(stringParameter); 
} 

Использование нуль:

Если вы ждете исключения, чтобы быть более или менее общим местом, вы можете вернуть нуль, а просто установить свой контракт на использование null когда-то незаконное происходит. Будьте осторожны, чтобы справиться с этим на стороне вызова, хотя!

Подобный этому подход используется для многих функций IndexOf, как на string. Они возвращают -1, а не null, но принцип тот же - одно значение, которое, как вы знаете, никогда не произойдет в реальных данных, и установите ваш контракт таким образом, чтобы это означало, что «это не сработало».

Это то, о чем я думал, когда раньше упоминал целостность данных и предположения. Что, если вы хотите вернуть это, словарь содержит пустую строку, и это должно означать нуль int. Внезапно вы больше не можете это передать. Так что да, это работает, но это решение, которое вы должны помнить. Убедитесь, что ваш «неудачный» случай никогда не будет результатом успешного прохождения.

public static int? GetParameter(this Dictionary<string, string> context, string parameterName) 
{ 
    string stringParameter; 
    if (!context.TryGetValue(parameterName, out stringParameter)) 
     return null; 

    int ret; 
    if (!int.TryParse(stringParameter, out ret)) 
     return null; 

    return ret; 
} 

Вернуться конкретный тип:

Это одна требует накладных расходов, но она имеет все любезность в качестве out параметра, фактически не требует его.

Тем не менее, я не уверен, действительно ли мне это нравится или нет. Это здорово в том, что он дает вам, но для меня это очень тяжело для того, для чего вы его используете. Но в любом случае это есть другой вариант.

public class ParseResult 
{ 
    public ParseResult(bool IsSuccess, int Result) 
    { 
     this.IsSuccess = IsSuccess; 
     this.Result = Result; 
    } 

    public bool IsSuccess { get; set; } 
    public int Result { get; set; } 
} 

public static ParseResult GetParameter(this Dictionary<string, string> context, string parameterName) 
{ 
    int ret; 
    string stringParameter; 
    if (context.TryGetValue(parameterName, out stringParameter) 
     && int.TryParse(stringParameter, out ret)) 
    { 
     return new ParseResult(true, ret); 
    } 
    else 
    { 
     return new ParseResult(false, 0); 
    } 
} 
+0

это хорошо ... спасибо много ... но если у меня есть еще 2 таких функции, как, например,« строка »и Функции типа «bool», теперь у меня есть конфликты между ними ...:/ – John

+1

@John, Назовите методы GetInt, GetBool, GetString или посмотрите на C# generics и 'Convert.ChangeType', чтобы избежать дублирования кода. – Guillaume

+0

Я не согласен, что это прекрасная модель для использования; Я предпочитаю представлять возвращаемые значения, как вы знаете, возвращаемые значения. [Есть даже предупреждение анализа кода об исключении параметров ...] (https://msdn.microsoft.com/en-us/library/ms182131.aspx) –

0

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

public static int GetParameter(this Dictionary<string, string> context, string parameterName) 
    { 
     int parameter; 
     string stringParameter; 
     context.TryGetValue(parameterName, out stringParameter); 
     int.TryParse(stringParameter, out parameter); 
     return parameter; 
    } 
+0

Как он отличает успех и неудачу? –

+0

@ThorstenDittmar - он этого не делает. Но, видимо, он тоже не сейчас. – Corak

+0

Он нужен? Из кода, который он опубликовал, я предположил, что он этого не делает, иначе он может просто вернуть нуль, как предположил Мэтью Хауген. –

0

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

public static string GetParameter(this Dictionary<string, string> context, 
            string parameterName) 
{ 
    string stringParameter = context[parameterName]; 
    return int.Parse(stringParameter); 
} 
+0

'public static int', его до сих пор неясно, что op надеется выйти из этой функции, хотя – Sayse

0

Вы можете сделать следующее:

public static int? GetParameter(this Dictionary<string, string> context, string parameterName) 
{ 
    string stringParameter; 
    if (!context.TryGetValue(parameterName, out stringParameter)) 
     return null; 

    int value; 
    if (!Int32.TryParse(stringParameter, out value)) 
     return null; 

    return value; 
} 

Это делает метод возвращает обнуляемые int. null будет возвращен в случае ошибок, в противном случае возвращается преобразованный int.

использовать его как:

int? value = GetParameter(...); 
if (value == null) 
    // error 
else 
    // use value.Value to access the real int. 
0

Нравится?

public static int GetParameter(this Dictionary<string, string> context, string parameterName) 
{ 
    string stringParameter; 
    context.TryGetValue(parameterName, out stringParameter); 
    int parameter; 
    int.TryParse(stringParameter, out parameter); 
    return parameter; 
} 

private int _personID; 
public void SomeFunction() 
{ 
    _personID = _classInstance.Context.GetParameter("PersonID"); 
} 
+0

Не знаете - вы уверены? –

0

Во-первых, я хочу сказать, что в подавляющем большинстве случаев вы должны обрабатывать условия отказа, бросая исключения.

Однако очень часто вы хотите иметь возможность вызвать метод для получения значения, в котором эта операция может завершиться неудачей, но вы не хотите генерировать исключение, чтобы выразить эту ошибку.

Это, очевидно, общая концепция, и стандартная библиотека .Net обращается к ней с использованием шаблона TryXXX().

Мне лично это не нравится, потому что это делает код более трудным для чтения, и это мешает делегатам, асинхронным и свободным интерфейсам.

Поэтому для обработки этих случаев мы создали собственный класс-оболочку.Вот пример урезанный (реальный код имеет много коды контрактов, а также позволяет дополнительные описательные строки ошибки и исключение):

public class Result<T> 
{ 
    public static Result<T> Success(T value) 
    { 
     return new Result<T>(value, true); 
    } 

    public static Result<T> Failure() 
    { 
     return new Result<T>(default(T), false); 
    } 

    private Result(T value, bool succeeded) 
    { 
     _value  = value; 
     _succeeded = succeeded; 
    } 

    public T Value 
    { 
     get 
     { 
      // Don't call this on failure! 
      Trace.Assert(_succeeded); 
      return _value; 
     } 
    } 

    public bool Succeeded 
    { 
     get 
     { 
      return _succeeded; 
     } 
    } 

    private readonly T _value; 
    private readonly bool _succeeded; 
} 

В вашем случае вы должны использовать это что-то вроде этого:

public static Result<int> GetParameter(this Dictionary<string, string> context, string parameterName) 
{ 
    string stringParameter; 
    context.TryGetValue(parameterName, out stringParameter); 
    int result; 

    if (int.TryParse(stringParameter, out result)) 
     return Result<int>.Success(result); 
    else 
     return Result<int>.Failure(); 
} 

И вызывающий код будет выглядеть следующим образом:

var personIdRetrieval = _classInstance.Context.GetParameter("PersonID"); 

if (personIdRetrieval.Succeeded) 
    _personID = personIdRetrieval.Value; 
else 
    // Handle failure. 
Смежные вопросы