Как разобрать строку в обнуляемый int - PullRequest
278 голосов
/ 05 сентября 2008

Я хочу разобрать строку в обнуляемый int в C #. то есть. Я хочу вернуть либо значение int строки, либо null, если оно не может быть проанализировано.

Я надеялся, что это сработает

int? val = stringVal as int?;

Но это не сработает, поэтому, как я это делаю сейчас, я написал этот метод расширения

public static int? ParseNullableInt(this string value)
{
    if (value == null || value.Trim() == string.Empty)
    {
        return null;
    }
    else
    {
        try
        {
            return int.Parse(value);
        }
        catch
        {
            return null;
        }
    }
}   

Есть ли лучший способ сделать это?

РЕДАКТИРОВАТЬ: Спасибо за предложения TryParse, я знал об этом, но это сработало примерно так же. Мне больше интересно знать, есть ли встроенный метод фреймворка, который будет анализировать напрямую в обнуляемый тип int?

Ответы [ 21 ]

327 голосов
/ 05 сентября 2008

int.TryParse, вероятно, немного проще:

public static int? ToNullableInt(this string s)
{
    int i;
    if (int.TryParse(s, out i)) return i;
    return null;
}

Редактировать @Glenn int.TryParse "встроен в структуру". Это и int.Parse являются способом для разбора строк в целые.

155 голосов
/ 05 сентября 2008

Вы можете сделать это в одной строке, используя условный оператор и тот факт, что вы можете преобразовать null в обнуляемый тип (две строки, если у вас нет уже существующего int, вы можете использовать его для вывода из TryParse):

Pre C # 7:

int tempVal;
int? val = Int32.TryParse(stringVal, out tempVal) ? Int32.Parse(stringVal) : (int?)null;

С обновленным синтаксисом C # 7, который позволяет объявлять выходную переменную в вызове метода, это становится еще проще.

int? val = Int32.TryParse(stringVal, out var tempVal) ? tempVal : (int?)null;
31 голосов
/ 28 октября 2008

У меня была эта проблема, с которой я столкнулся (в конце концов, if и 2 return s слишком длинны!):

int? ParseNInt (string val)
{
    int i;
    return int.TryParse (val, out i) ? (int?) i : null;
}

На более серьезном замечании, старайтесь не смешивать int, который является ключевым словом C #, с Int32, который является типом .NET Framework BCL - хотя это работает, он просто делает код неопрятным.

15 голосов
/ 25 июня 2011

Гленн Славен : мне больше интересно знать, есть встроенный метод каркаса который будет разбираться непосредственно в обнуляемый int?

Существует такой подход, который непосредственно анализирует обнуляемое int (а не только int), если значение допустимо, например, пустая или пустая строка, но выдает исключение для недопустимых значений, поэтому вам нужно будет перехватить исключение и вернуть значение по умолчанию для этих ситуаций:

public static T Parse<T>(object value)
{
    try { return (T)System.ComponentModel.TypeDescriptor.GetConverter(typeof(T)).ConvertFrom(value.ToString()); }
    catch { return default(T); }
}

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

enum Fruit { Orange, Apple }
var res1 = Parse<Fruit>("Apple");
var res2 = Parse<Fruit?>("Banana");
var res3 = Parse<int?>("100") ?? 5; //use this for non-zero default
var res4 = Parse<Unit>("45%");

NB: В преобразователе есть метод IsValid, который можно использовать вместо захвата исключения (сгенерированные исключения приводят к ненужным издержкам , если ожидается). К сожалению, он работает только с .NET 4, но есть проблема, при которой он не проверяет ваш языковой стандарт при проверке правильных форматов DateTime, см. bug 93559 .

8 голосов
/ 05 сентября 2008

Попробуйте это:

public static int? ParseNullableInt(this string value)
{
    int intValue;
    if (int.TryParse(value, out intValue))
        return intValue;
    return null;
}
7 голосов
/ 22 марта 2011

Старая тема, но как насчет:

public static int? ParseToNullableInt(this string value)
{
     return String.IsNullOrEmpty(value) ? null : (int.Parse(value) as int?);
}

Мне больше нравится это как требование, где анализировать нуль, версия TryParse не выдаст ошибку, например. ToNullableInt32 (XXX). Это может привести к нежелательным тихим ошибкам.

5 голосов
/ 21 июня 2011

Я чувствую, что мое решение очень чистое и приятное:

public static T? NullableParse<T>(string s) where T : struct
{
    try
    {
        return (T)typeof(T).GetMethod("Parse", new[] {typeof(string)}).Invoke(null, new[] { s });
    }
    catch (Exception)
    {
        return null;
    }
}

Это, конечно, универсальное решение, которое требует только, чтобы аргумент универсального элемента имел статический метод "Parse (string)". Это работает для чисел, логических, DateTime и т. Д.

5 голосов
/ 24 октября 2018
var result = int.TryParse(foo, out var f) ? f : default(int?);

Источники:

4 голосов
/ 10 ноября 2011

Вы можете забыть все остальные ответы - есть отличное общее решение: http://cleansharp.de/wordpress/2011/05/generischer-typeconverter/

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

string value = null;
int? x = value.ConvertOrDefault();

, а также:

object obj = 1;  

string value = null;
int x = 5;
if (value.TryConvert(out x))
    Console.WriteLine("TryConvert example: " + x); 

bool boolean = "false".ConvertOrDefault();
bool? nullableBoolean = "".ConvertOrDefault();
int integer = obj.ConvertOrDefault();
int negativeInteger = "-12123".ConvertOrDefault();
int? nullableInteger = value.ConvertOrDefault();
MyEnum enumValue = "SecondValue".ConvertOrDefault();

MyObjectBase myObject = new MyObjectClassA();
MyObjectClassA myObjectClassA = myObject.ConvertOrDefault();
3 голосов
/ 12 марта 2018

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

public static int ParseInt(this string value, int defaultIntValue = 0)
        {
            return int.TryParse(value, out var parsedInt) ? parsedInt : defaultIntValue;
        }

public static int? ParseNullableInt(this string value)
        {
            if (string.IsNullOrEmpty(value))
                return null;

            return value.ParseInt();
        }
...